Skip to content

Commit 5438daf

Browse files
committed
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

File tree

17 files changed

+264
-440
lines changed

17 files changed

+264
-440
lines changed

.gitignore

Lines changed: 15 additions & 14 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 6 additions & 52 deletions
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

Lines changed: 7 additions & 15 deletions
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

Lines changed: 25 additions & 73 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 2 additions & 1 deletion
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)