Skip to content

Commit 5438daf

Browse files
committedAug 18, 2019
Update open exchange chess engine handling
Execute (open exchange chess) engines directly from their native library path to support Android 10.
1 parent 49da0ec commit 5438daf

17 files changed

+264
-440
lines changed
 

‎.gitignore

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
*.iml
22
.gradle
3-
/local.properties
4-
/.idea/caches
5-
/.idea/libraries
6-
/.idea/modules.xml
7-
/.idea/workspace.xml
8-
/.idea/navEditor.xml
9-
/.idea/assetWizardSettings.xml
3+
local.properties
4+
.idea/caches
5+
.idea/libraries
6+
.idea/modules.xml
7+
.idea/workspace.xml
8+
.idea/navEditor.xml
9+
.idea/assetWizardSettings.xml
10+
.idea/misc.xml
1011
.DS_Store
11-
/captures
12+
captures
1213
.externalNativeBuild
13-
/build
14-
/scidOnTheGo/build
15-
/chessEngineSupportLibrary/build
16-
/scidOnTheGo/src/main/jniLibs
17-
/scidOnTheGo/src/main/libs
18-
/scidOnTheGo/src/main/obj
14+
build
15+
scidOnTheGo/build
16+
chessEngineSupportLibrary/build
17+
scidOnTheGo/src/main/jniLibs
18+
scidOnTheGo/src/main/libs
19+
scidOnTheGo/src/main/obj

‎build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
buildscript {
33
repositories {
44
jcenter()
5+
google()
56
}
67
dependencies {
78
classpath 'com.android.tools.build:gradle:3.4.2'
@@ -11,5 +12,6 @@ buildscript {
1112
allprojects {
1213
repositories {
1314
jcenter()
15+
google()
1416
}
1517
}

‎chessEngineSupportLibrary/src/main/java/com/kalab/chess/enginesupport/ChessEngine.java

+6-52
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,28 @@
1313
*/
1414
package com.kalab.chess.enginesupport;
1515

16-
import java.io.File;
17-
import java.io.FileNotFoundException;
18-
import java.io.FileOutputStream;
19-
import java.io.IOException;
20-
import java.io.InputStream;
21-
2216
import android.app.Activity;
2317
import android.content.ComponentName;
24-
import android.content.ContentResolver;
2518
import android.content.Intent;
26-
import android.net.Uri;
2719
import android.os.Bundle;
28-
import android.util.Log;
2920

3021
public class ChessEngine {
3122

3223
private static final String TAG = ChessEngine.class.getSimpleName();
3324

3425
private final String name;
3526
private final String fileName;
27+
private final String enginePath;
3628
private final String authority;
3729
private final String packageName;
3830
private final int versionCode;
3931
private final String licenseCheckActivity;
4032

41-
public ChessEngine(String name, String fileName, String authority,
42-
String packageName, int versionCode, String licenseCheckActivity) {
33+
public ChessEngine(String name, String fileName, String enginePath, String authority,
34+
String packageName, int versionCode, String licenseCheckActivity) {
4335
this.name = name;
4436
this.fileName = fileName;
37+
this.enginePath = enginePath;
4538
this.authority = authority;
4639
this.packageName = packageName;
4740
this.versionCode = versionCode;
@@ -56,47 +49,8 @@ public String getFileName() {
5649
return this.fileName;
5750
}
5851

59-
public Uri getUri() {
60-
return Uri.parse("content://" + authority + "/" + fileName);
61-
}
62-
63-
public File copyToFiles(ContentResolver contentResolver, File destination)
64-
throws FileNotFoundException, IOException {
65-
Uri uri = getUri();
66-
File output = new File(destination, uri.getPath().toString());
67-
copyUri(contentResolver, uri, output.getAbsolutePath());
68-
return output;
69-
}
70-
71-
public void copyUri(final ContentResolver contentResolver,
72-
final Uri source, String targetFilePath) throws IOException,
73-
FileNotFoundException {
74-
InputStream istream = contentResolver.openInputStream(source);
75-
copyFile(istream, targetFilePath);
76-
setExecutablePermission(targetFilePath);
77-
}
78-
79-
private void copyFile(InputStream istream, String targetFilePath)
80-
throws FileNotFoundException, IOException {
81-
FileOutputStream fout = new FileOutputStream(targetFilePath);
82-
byte[] b = new byte[1024];
83-
int numBytes = 0;
84-
while ((numBytes = istream.read(b)) != -1) {
85-
fout.write(b, 0, numBytes);
86-
}
87-
istream.close();
88-
fout.close();
89-
}
90-
91-
private void setExecutablePermission(String engineFileName)
92-
throws IOException {
93-
String cmd[] = { "chmod", "744", engineFileName };
94-
Process process = Runtime.getRuntime().exec(cmd);
95-
try {
96-
process.waitFor();
97-
} catch (InterruptedException e) {
98-
Log.e(TAG, e.getMessage(), e);
99-
}
52+
public String getEnginePath() {
53+
return this.enginePath;
10054
}
10155

10256
public String getPackageName() {

‎chessEngineSupportLibrary/src/main/java/com/kalab/chess/enginesupport/ChessEngineProvider.java

+7-15
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,19 @@
1313
*/
1414
package com.kalab.chess.enginesupport;
1515

16-
import java.io.File;
17-
import java.io.FileNotFoundException;
18-
import java.io.IOException;
19-
20-
import android.annotation.TargetApi;
2116
import android.content.ContentProvider;
2217
import android.content.ContentValues;
2318
import android.content.res.AssetFileDescriptor;
2419
import android.content.res.AssetManager;
2520
import android.database.Cursor;
2621
import android.net.Uri;
27-
import android.os.Build;
2822
import android.os.ParcelFileDescriptor;
2923
import android.util.Log;
3024

25+
import java.io.File;
26+
import java.io.FileNotFoundException;
27+
import java.io.IOException;
28+
3129
public class ChessEngineProvider extends ContentProvider {
3230

3331
private static final String MIME_TYPE = "application/x-chess-engine";
@@ -70,14 +68,8 @@ public AssetFileDescriptor openAssetFile(Uri uri, String mode)
7068
return descriptor;
7169
}
7270

73-
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
7471
private String getNativeLibraryDir() {
75-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
76-
return getContext().getApplicationInfo().nativeLibraryDir;
77-
} else {
78-
return getContext().getApplicationInfo().dataDir + File.separator
79-
+ "lib";
80-
}
72+
return getContext().getApplicationInfo().nativeLibraryDir;
8173
}
8274

8375
public ParcelFileDescriptor openLibFile(File f)
@@ -93,7 +85,7 @@ public String getType(Uri uri) {
9385

9486
@Override
9587
public Cursor query(Uri uri, String[] projection, String selection,
96-
String[] selectionArgs, String sortOrder) {
88+
String[] selectionArgs, String sortOrder) {
9789
throw new UnsupportedOperationException(UNSUPPORTED);
9890
}
9991

@@ -109,7 +101,7 @@ public Uri insert(Uri uri, ContentValues values) {
109101

110102
@Override
111103
public int update(Uri uri, ContentValues values, String selection,
112-
String[] selectionArgs) {
104+
String[] selectionArgs) {
113105
throw new UnsupportedOperationException(UNSUPPORTED);
114106
}
115107
}

‎chessEngineSupportLibrary/src/main/java/com/kalab/chess/enginesupport/ChessEngineResolver.java

+25-73
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,11 @@
1313
*/
1414
package com.kalab.chess.enginesupport;
1515

16-
import java.io.File;
17-
import java.io.FileNotFoundException;
18-
import java.io.IOException;
19-
import java.util.ArrayList;
20-
import java.util.HashMap;
21-
import java.util.List;
22-
import java.util.Map;
23-
24-
import org.xmlpull.v1.XmlPullParserException;
25-
2616
import android.app.Activity;
2717
import android.content.Context;
2818
import android.content.Intent;
2919
import android.content.pm.ActivityInfo;
30-
import android.content.pm.PackageInfo;
20+
import android.content.pm.ApplicationInfo;
3121
import android.content.pm.PackageManager;
3222
import android.content.pm.PackageManager.NameNotFoundException;
3323
import android.content.pm.ResolveInfo;
@@ -37,6 +27,15 @@
3727
import android.os.Bundle;
3828
import android.util.Log;
3929

30+
import org.xmlpull.v1.XmlPullParserException;
31+
32+
import java.io.File;
33+
import java.io.IOException;
34+
import java.util.ArrayList;
35+
import java.util.HashMap;
36+
import java.util.List;
37+
import java.util.Map;
38+
4039
public class ChessEngineResolver {
4140

4241
private static final String ENGINE_PROVIDER_MARKER = "intent.chess.provider.ENGINE";
@@ -46,12 +45,13 @@ public class ChessEngineResolver {
4645
private Context context;
4746
private String target;
4847
/** map of package -> activity for license checks */
49-
Map<String, String> licenseCheckActivities = new HashMap<String, String>();
48+
private Map<String, String> licenseCheckActivities = new HashMap<>();
5049

50+
@SuppressWarnings("deprecation")
5151
public ChessEngineResolver(Context context) {
5252
super();
5353
this.context = context;
54-
this.target = Build.CPU_ABI;
54+
this.target = Build.CPU_ABI; // use Build.SUPPORTED_ABIS[0] from API level 21 onwards
5555
sanitizeArmV6Target();
5656
}
5757

@@ -68,7 +68,7 @@ private void sanitizeArmV6Target() {
6868
*/
6969
public List<ChessEngine> resolveEngines() {
7070
resolveLicenseCheckActivitiesPerPackage();
71-
List<ChessEngine> result = new ArrayList<ChessEngine>();
71+
List<ChessEngine> result = new ArrayList<>();
7272
final Intent engineProviderIntent = new Intent(ENGINE_PROVIDER_MARKER);
7373
List<ResolveInfo> engineProviderList = context.getPackageManager()
7474
.queryIntentActivities(engineProviderIntent,
@@ -130,7 +130,7 @@ private List<ChessEngine> resolveEnginesForPackage(
130130
}
131131

132132
private void parseEngineListXml(XmlResourceParser parser, String authority,
133-
List<ChessEngine> result, String packageName) {
133+
List<ChessEngine> result, String packageName) {
134134
try {
135135
int eventType = parser.getEventType();
136136
while (eventType != XmlResourceParser.END_DOCUMENT) {
@@ -149,7 +149,7 @@ private void parseEngineListXml(XmlResourceParser parser, String authority,
149149
}
150150

151151
private void addEngine(List<ChessEngine> result, XmlResourceParser parser,
152-
String authority, String packageName) {
152+
String authority, String packageName) {
153153
if (parser.getName().equalsIgnoreCase("engine")) {
154154
String fileName = parser.getAttributeValue(null, "filename");
155155
String title = parser.getAttributeValue(null, "name");
@@ -165,66 +165,18 @@ private void addEngine(List<ChessEngine> result, XmlResourceParser parser,
165165
} catch (NameNotFoundException e) {
166166
Log.e(TAG, e.getMessage());
167167
}
168-
result.add(new ChessEngine(title, fileName, authority,
169-
packageName, versionCode, licenseCheckActivities
170-
.get(packageName)));
171-
}
172-
}
173-
}
174-
}
175-
176-
/**
177-
* Ensure that the engine is current. It re-copies the engine if it was not
178-
* current.
179-
*
180-
* @param fileName
181-
* the file name of the engine
182-
* @param packageName
183-
* the package name of the engine
184-
* @param versionCode
185-
* the (installed) version code of the engine
186-
* @param destination
187-
* the destination folder to copy a new engine to
188-
* @return the new version of the engine, -1 in case of an error (IOError or
189-
* if no engine was found)
190-
*/
191-
public int ensureEngineVersion(String fileName, String packageName,
192-
int versionCode, File destination) {
193-
int result = -1;
194-
PackageInfo packageInfo;
195-
Log.d(TAG, "checking engine " + fileName + ", " + packageName
196-
+ ", version " + versionCode);
197-
try {
198-
packageInfo = context.getPackageManager().getPackageInfo(
199-
packageName, 0);
200-
if (packageInfo.versionCode > versionCode
201-
|| !(new File(destination, fileName).exists())) {
202-
// package is updated or file is missing, need to copy engine
203-
// again
204-
for (ChessEngine engine : resolveEngines()) {
205-
if (engine.getPackageName().equals(packageName)
206-
&& engine.getFileName().equals(fileName)) {
207-
try {
208-
Log.d(TAG, "engine is outdated");
209-
engine.copyToFiles(context.getContentResolver(),
210-
destination);
211-
result = packageInfo.versionCode;
212-
} catch (FileNotFoundException e) {
213-
Log.e(TAG, e.getMessage(), e);
214-
} catch (IOException e) {
215-
Log.e(TAG, e.getMessage(), e);
216-
}
217-
break;
168+
try {
169+
ApplicationInfo app = context.getPackageManager().getApplicationInfo(packageName, 0);
170+
String enginePath = new File(app.nativeLibraryDir, fileName).getAbsolutePath();
171+
result.add(new ChessEngine(title, fileName, enginePath, authority,
172+
packageName, versionCode, licenseCheckActivities
173+
.get(packageName)));
174+
} catch (NameNotFoundException e) {
175+
Log.e(TAG, e.getLocalizedMessage(), e);
218176
}
219177
}
220-
} else {
221-
Log.d(TAG, "engine is up-to-date");
222-
result = packageInfo.versionCode;
223178
}
224-
} catch (NameNotFoundException e) {
225-
Log.w(TAG, "package " + packageName + " not found");
226179
}
227-
return result;
228180
}
229181

230182
/**
@@ -242,7 +194,7 @@ public int ensureEngineVersion(String fileName, String packageName,
242194
* If a license check is performed the caller must check the result in onActivityResult()
243195
*/
244196
public boolean checkLicense(Activity caller, int requestCode,
245-
String fileName, String packageName) {
197+
String fileName, String packageName) {
246198
Log.d(TAG, "checking license for engine " + fileName + ", "
247199
+ packageName);
248200
for (ChessEngine engine : resolveEngines()) {

‎scidOnTheGo/build.gradle

+5
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,10 @@ android {
2828
}
2929

3030
dependencies {
31+
implementation 'com.android.support:appcompat-v7:28.0.0'
32+
implementation 'com.android.support:design:28.0.0'
33+
implementation 'com.android.support:recyclerview-v7:28.0.0'
34+
implementation 'com.android.support:support-compat:28.0.0'
35+
3136
api project(':chessEngineSupportLibrary')
3237
}

‎scidOnTheGo/src/main/java/org/scid/android/ExportPgnActivity.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import android.app.Activity;
66
import android.content.Intent;
7+
import android.os.AsyncTask;
78
import android.os.Bundle;
89

910
public class ExportPgnActivity extends Activity {
@@ -27,6 +28,6 @@ protected Boolean doInBackground(Void... params) {
2728
return false;
2829
}
2930
}
30-
}).execute();
31+
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
3132
}
3233
}

0 commit comments

Comments
 (0)
Failed to load comments.