Skip to content

Commit

Permalink
Have the engine access weights from external storage
Browse files Browse the repository at this point in the history
  • Loading branch information
lealgo committed May 17, 2020
1 parent af7d272 commit 62e19e9
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 23 deletions.
2 changes: 2 additions & 0 deletions LeelaChessEngine/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
android.enableJetifier=true
android.useAndroidX=true
1 change: 1 addition & 0 deletions LeelaChessEngine/leelaChessEngine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ android {

dependencies {
implementation project(':chessEngineSupportLibrary')
implementation 'androidx.core:core:1.2.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package="com.kalab.chess.leelaengine"
android:versionCode="1"
android:versionName="0.25dev">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package com.kalab.chess.leelaengine;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -21,12 +26,20 @@
import android.text.style.RelativeSizeSpan;
import android.text.style.ForegroundColorSpan;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MainActivity extends Activity {

private class HeaderView extends LinearLayout {
public HeaderView(Context context) {
super(context);

ImageView icon = new ImageView(context);
icon.setImageResource(R.drawable.ic_launcher);
int iconSize = getRawPixels(48f);
Expand All @@ -35,7 +48,6 @@ public HeaderView(Context context) {
iconParams.height = iconSize;
iconParams.gravity = Gravity.CENTER_VERTICAL;
addView(icon, iconParams);

TextView text = new TextView(context);
text.setGravity(Gravity.CENTER);
text.setText(R.string.app_name);
Expand All @@ -61,22 +73,26 @@ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
}
}

private static String baseDirPath = "lc0";
private static String weightsDirPath = "networks";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createDirectories();
createLayout();
}

void createLayout() {
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
int spacing = getRawPixels(12f);
layout.setPadding(spacing, spacing, spacing, spacing);

HeaderView header = new HeaderView(this);
LinearLayout.LayoutParams headerParams = LinearLayoutParams();
headerParams.gravity = Gravity.CENTER_HORIZONTAL;
layout.addView(header, headerParams);

layout.addView(new VerticalSeparator(this));

TextView label = new TextView(this);
label.setMovementMethod(LinkMovementMethod.getInstance());
label.setText(getLabel());
Expand All @@ -85,7 +101,9 @@ public void onCreate(Bundle savedInstanceState) {
labelParams.weight = 1.0f;
labelParams.topMargin = spacing;
layout.addView(label, labelParams);

TextView notice = new TextView(this);
notice.setText(getNotice());
layout.addView(notice);
setContentView(layout);
}

Expand All @@ -104,57 +122,50 @@ String getNetworkWeights() {

private CharSequence getLabel() {
SpannableStringBuilder b = new SpannableStringBuilder();

appendLine(b, getText(R.string.includes_the_following_engines));

appendDetail(b, "Chess Engine Version", getVersionName());

appendDetail(b, "Network Weights File", getNetworkWeights());

appendLine(b, getText(R.string.to_use_them));

appendLink(b, getText(R.string.released_under), getText(R.string.source_code));

return b;
}

private CharSequence getNotice() {
if (!getPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE))
return getText(R.string.storage_permission);
else
return null;
}

private static void appendLine(SpannableStringBuilder b, CharSequence line) {
b.append(line);
b.append("\n\n");
}

private static void appendDetail(SpannableStringBuilder b, String title, String subtitle) {
b.append(" ");

int nameStart = b.length();
b.append(title);
b.setSpan(new StyleSpan(Typeface.BOLD), nameStart, b.length(), 0);

b.append("\n ");

int subtitleStart = b.length();
b.append(subtitle);

b.setSpan(new RelativeSizeSpan(0.8f), subtitleStart, b.length(), 0);
b.setSpan(new ForegroundColorSpan(0xff808080), subtitleStart, b.length(), 0);

b.append("\n\n");
}

private void appendLink(SpannableStringBuilder b, CharSequence line, final CharSequence link) {
b.append(line);
b.append(" (");

int downloadLinkStart = b.length();

b.append("source code");
b.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
launchUri(link);
}
}, downloadLinkStart, b.length(), 0);

b.append(").");
}

Expand All @@ -173,4 +184,86 @@ private int getRawPixels(float dp) {
private LinearLayout.LayoutParams LinearLayoutParams() {
return new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
}

/** Create directory structure on external storage. */
private void createDirectories() {
if (!getPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE))
return;
copyAssets(baseDirPath, weightsDirPath);
}

boolean getPermission(String permission) {
if (ContextCompat.checkSelfPermission(this, permission) ==
PackageManager.PERMISSION_GRANTED) {
return true;
} else {
ActivityCompat.requestPermissions(this, new String[]{permission}, 0);
return false;
}
}

@Override
public void onRequestPermissionsResult(int code, String[] permissions, int[] results) {
for (int i = 0; i < permissions.length; ++i) {
if (results[i] == PackageManager.PERMISSION_GRANTED) {
if (permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
createDirectories();
}
}
}
}

/** Copy assets to external storage. */
private void copyAssets(String base, String dir) {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list(dir);
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
if (files != null) {
for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
File outDir = new File(Environment.getExternalStorageDirectory() + File.separator + base + File.separator + dir);
outDir.mkdirs();
File outFile = new File(outDir, filename);

AssetFileDescriptor asset = assetManager.openFd(dir + File.separator + filename);
if (asset.getLength() != outFile.length()) {
in = asset.createInputStream();
out = new FileOutputStream(outFile);
copyFile(in, out);
}
} catch (IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
}

private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Leela Chess Zero Engine</string>
<string name="app_name">Leela Chess Zero</string>
<string name="network_weights">591226</string>
<string name="includes_the_following_engines">This package provides the Leela Chess Zero engine.</string>
<string name="to_use_them">To use it, you need a chess application compatible with the Open Exchange protocol.</string>
<string name="released_under">Leela Chess Zero is released under the terms of the GNU General Public License v3</string>
<string name="build">Build</string>
<string name="source_code">https://github.com/LeelaChessZero/lc0</string>
<string name="source_code">https://github.com/LeelaChessZero</string>
<string name="storage_permission">To function properly, the engine needs to access its network weights file from the local storage. Please give storage permission to this application.</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
<engine
name="Leela Chess Zero"
filename="liblc0.so"
target="armeabi-v7a|arm64-v8a" />
target="armeabi-v7a|arm64-v8a|x86" />

</enginelist>

0 comments on commit 62e19e9

Please sign in to comment.