增加google drive支持

This commit is contained in:
CounterFire2023 2023-09-01 16:16:43 +08:00
parent dfb689522e
commit c7a74b07d0
13 changed files with 504 additions and 90 deletions

View File

@ -244,6 +244,14 @@ NS_CC_BEGIN
});
return result == 0 ? 1 : 0;
}
JNIEXPORT jstring JNICALL JNI_JCFW(decryptPass)(JNIEnv *env, jclass clazz, jstring jaccount, jstring jpass) {
std::string pass_encrypted = JniHelper::jstring2string(jpass);
std::string account = JniHelper::jstring2string(jaccount);
std::string keyStr = account + "0x741482aE1480E552735E44Ff3A733448AcBbeD8d";
std::string passDecrypt = decrypt_aes(pass_encrypted, keyStr);
return env->NewStringUTF(passDecrypt.c_str());
}
#endif
}

File diff suppressed because one or more lines are too long

View File

@ -138,6 +138,7 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.googleusercontent.apps.53206975661-asnf3qe4bg29p8h981pgf099osvrjbme" />
<data android:scheme="cebg" android:path="/apple_login_result" />
</intent-filter>
</activity>
@ -149,20 +150,20 @@
<activity
android:name=".apple.AppleLoginActivity"
android:theme="@style/WebViewTheme" />
<activity
android:name=".apple.AppleLoginCbActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<!-- <activity-->
<!-- android:name=".apple.AppleLoginCbActivity"-->
<!-- android:exported="true">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.VIEW" />-->
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- <category android:name="android.intent.category.DEFAULT" />-->
<!-- <category android:name="android.intent.category.BROWSABLE" />-->
<data
android:scheme="cebg"
android:path="/apple_login_result" />
</intent-filter>
</activity>
<!-- <data-->
<!-- android:scheme="cebg"-->
<!-- android:path="/apple_login_result" />-->
<!-- </intent-filter>-->
<!-- </activity>-->
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"

View File

@ -115,6 +115,17 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
exclude("META-INF/DEPENDENCIES")
exclude("META-INF/LICENSE")
exclude("META-INF/LICENSE.txt")
exclude("META-INF/license.txt")
exclude("META-INF/NOTICE")
exclude("META-INF/NOTICE.txt")
exclude("META-INF/notice.txt")
exclude("META-INF/ASL2.0")
exclude("META-INF/*.kotlin_module")
}
}
android.applicationVariants.all { variant ->
@ -171,4 +182,15 @@ dependencies {
// end of firebase
// google pay
implementation "com.android.billingclient:billing:6.0.1"
// google drive
implementation('com.google.api-client:google-api-client-android:2.2.0') {
exclude group: 'org.apache.httpcomponents'
exclude module: 'guava-jdk5'
}
implementation 'com.google.http-client:google-http-client-android:1.23.0'
implementation('com.google.apis:google-api-services-drive:v3-rev20230815-2.0.0') {
exclude group: 'org.apache.httpcomponents'
exclude module: 'guava-jdk5'
}
}

View File

@ -1,8 +1,8 @@
package com.cege.games.release;
import static org.cocos2dx.lib.Cocos2dxHelper.getActivity;
import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@ -33,6 +33,7 @@ import com.cege.games.release.activity.CustomCaptureActivity;
import com.cege.games.release.activity.WebPageActivity;
import com.cege.games.release.apple.AppleLoginActivity;
import com.cege.games.release.dialog.QRCodeActivity;
import com.cege.games.release.wallet.WalletUtil;
import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
@ -52,12 +53,13 @@ import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.Task;
import com.google.api.services.drive.DriveScopes;
import com.google.common.collect.Maps;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.jc.jcfw.JcSDK;
import com.jc.jcfw.appauth.AuthStateManager;
import com.jc.jcfw.appauth.JConfiguration;
import com.jc.jcfw.google.PayClient;
import com.jc.jcfw.util.IDUtils;
import com.jc.jcfw.util.JsonUtils;
import com.king.zxing.CameraScan;
import com.king.zxing.util.CodeUtils;
@ -85,10 +87,12 @@ import org.cocos2dx.lib.Cocos2dxHelper;
import org.cocos2dx.lib.CocosJSHelper;
import org.json.JSONException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -114,6 +118,10 @@ public class MainActivity extends UnityPlayerActivity
private static final int RC_AUTH = 0X04;
// google signin
private static final int RC_SIGN_IN = 0X05;
// code for request drive to upload
private static final int RC_REQUEST_DRIVE_TO_UPLOAD = 0X051;
// code for request drive to download
private static final int RC_REQUEST_DRIVE_TO_READ = 0X052;
public static final int RC_CAMERA = 0X011;
@ -122,8 +130,6 @@ public class MainActivity extends UnityPlayerActivity
public static final int FILE_SELECTOR_CODE = 0X014;
private String title;
private String funId;
private String oid;
private QRCodeActivity qrCodeActivity;
// AppAuth
@ -151,10 +157,9 @@ public class MainActivity extends UnityPlayerActivity
private FirebaseAnalytics mFirebaseAnalytics;
private AppEventsLogger fbLogger;
// store params for request permission or jump to other activity
private final Map<Integer, Map<String, String>> paramCache = Maps.newHashMap();
private AccountManager accountManager;
private String accountType = "com.cege.games.auth";
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -171,9 +176,8 @@ public class MainActivity extends UnityPlayerActivity
// begin of google sign
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.EMAIL))
.requestIdToken(getString(R.string.default_web_client_id1))
.requestScopes(new Scope(Scopes.EMAIL), new Scope("https://www.googleapis.com/auth/drive.appdata"))
// .requestScopes(new Scope("https://www.googleapis.com/auth/drive.appdata"))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
// end of google sign
@ -197,10 +201,6 @@ public class MainActivity extends UnityPlayerActivity
PayClient payClient = PayClient.getInstance();
payClient.init(this);
accountManager = AccountManager.get(this.getApplicationContext());
String id = IDUtils.id(this);
Log.i(TAG, "custom id:: " + id);
Log.i(TAG, "build info::" + IDUtils.getBuildInfo());
}
@Override
@ -243,9 +243,22 @@ public class MainActivity extends UnityPlayerActivity
Uri uri = data.getData();
shareToTikTok(funId, uri);
break;
case RC_REQUEST_DRIVE_TO_UPLOAD:
mExecutor.submit(this::saveToDriveAppFolder);
break;
case RC_REQUEST_DRIVE_TO_READ:
mExecutor.submit(this::loadDrivePass);
break;
}
} else {
boolean next = false;
if (requestCode == RC_REQUEST_DRIVE_TO_UPLOAD || requestCode == RC_REQUEST_DRIVE_TO_READ) {
Map<String, String> params = paramCache.get(requestCode);
if (params != null) {
JcSDK.nativeCb(params.get("funid"), "activity result with code: " + resultCode, null);
paramCache.remove(requestCode);
}
}
if (requestCode == REQUEST_CODE_SCAN && data != null) {
if (data.getBooleanExtra("localImg", false)) {
startPhotoCode(this.funId);
@ -355,7 +368,6 @@ public class MainActivity extends UnityPlayerActivity
runOnUiThread(() -> {
this.startActivityForResult(intent, REQUEST_CODE_SCAN, optionsCompat.toBundle());
});
}
private void asyncThread(Runnable runnable) {
@ -417,7 +429,7 @@ public class MainActivity extends UnityPlayerActivity
startActivityForResult(signInIntent, RC_SIGN_IN);
}
} else {
Log.i(TAG, "no gms, use app auth");
// Log.i(TAG, "no gms, use app auth");
AuthState state = mAuthStateManager.getCurrent();
if (state.isAuthorized() && state.getIdToken() != null) {
Log.w(TAG, "getNeedsTokenRefresh: " + state.getNeedsTokenRefresh());
@ -430,7 +442,7 @@ public class MainActivity extends UnityPlayerActivity
} else {
Log.w(TAG, "already login, accessToken not expired");
Log.w(TAG, "id token : " + state.getIdToken());
runOnUiThread(() -> successSdkCb(state.getIdToken()));
JcSDK.nativeCb(this.funId, null, state.getIdToken());
}
} else {
mExecutor.submit(this::doAuth);
@ -450,7 +462,7 @@ public class MainActivity extends UnityPlayerActivity
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
Log.w(TAG, "signIn success: ");
Log.w(TAG, "gsa idToken: " + account.getIdToken());
runOnUiThread(() -> successSdkCb(account.getIdToken()));
JcSDK.nativeCb(this.funId, null, account.getIdToken());
// Signed in successfully, show authenticated UI.
} catch (ApiException e) {
// The ApiException status code indicates the detailed failure reason.
@ -543,6 +555,9 @@ public class MainActivity extends UnityPlayerActivity
mClientId.get(),
ResponseTypeValues.CODE,
mConfiguration.getRedirectUri())
// apple need `form_post` when authorization_scope has `name email `
// .setResponseMode("form_post")
// .setResponseType("code id_token")
.setScope(mConfiguration.getScope());
if (!TextUtils.isEmpty(loginHint)) {
@ -709,20 +724,10 @@ public class MainActivity extends UnityPlayerActivity
Log.d(TAG, "login success, auth state: " + state.isAuthorized());
Log.d(TAG, "app auth idToken: " + state.getIdToken());
mAuthStateManager.replace(state);
runOnUiThread(() -> successSdkCb(state.getIdToken()));
JcSDK.nativeCb(this.funId, null, state.getIdToken());
}
}
@MainThread
private void successSdkCb(String idToken) {
JcSDK.nativeCb(this.funId, null, idToken);
}
@MainThread
private void errorSdkCb(String errMsg) {
JcSDK.nativeCb(this.funId, errMsg, null);
}
// sign with tiktok
public void signWithTiktok(String funId) {
this.funId = funId;
@ -769,20 +774,20 @@ public class MainActivity extends UnityPlayerActivity
AccessToken accessToken = AccessToken.getCurrentAccessToken();
Log.d(TAG, "Login Success:: accessToken: " + accessToken.getToken());
if (!verifyFbAccessToken(accessToken)) {
runOnUiThread(() -> errorSdkCb("access token expired"));
JcSDK.nativeCb(MainActivity.app.funId, "access token expired", null);
}
}
@Override
public void onCancel() {
Log.d(TAG, "Login cancel");
runOnUiThread(() -> errorSdkCb("user login cancel"));
JcSDK.nativeCb(MainActivity.app.funId, "user login cancel", null);
}
@Override
public void onError(FacebookException exception) {
Log.i(TAG, "Login error: " + exception.getMessage());
runOnUiThread(() -> errorSdkCb(exception.getMessage()));
JcSDK.nativeCb(MainActivity.app.funId, exception.getMessage(), null);
}
});
}
@ -791,12 +796,9 @@ public class MainActivity extends UnityPlayerActivity
Log.i(TAG, "login with facebook: " + funId);
this.funId = funId;
AccessToken accessToken = AccessToken.getCurrentAccessToken();
// Log.d("Success", "Login:: accessToken: " + accessToken.getToken());
if (!verifyFbAccessToken(accessToken)) {
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile", "email"));
}
// AccessToken.getCurrentAccessToken();
}
public void shareWithFacebook(String content) {
@ -810,7 +812,7 @@ public class MainActivity extends UnityPlayerActivity
private boolean verifyFbAccessToken(AccessToken accessToken) {
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();
if (isLoggedIn) {
runOnUiThread(() -> successSdkCb(accessToken.getToken()));
JcSDK.nativeCb(this.funId, null, accessToken.getToken());
return true;
} else {
return false;
@ -852,9 +854,6 @@ public class MainActivity extends UnityPlayerActivity
Intent intent = new Intent(this, WebPageActivity.class);
intent.putExtra("url", url);
startActivity(intent);
// picker video file and share to tiktok
// openFileSelector();
// authenticateToEncrypt("1111");
});
}
@ -905,19 +904,48 @@ public class MainActivity extends UnityPlayerActivity
Log.i(TAG, "passStorageState with: " + account);
}
private void saveToDriveAppFolder() {
Map<String, String> params = paramCache.get(RC_REQUEST_DRIVE_TO_UPLOAD);
if (params == null) {
return;
}
WalletUtil.saveToDriveAppFolder(params.get("funid"), params.get("account"), JcSDK::nativeCb);
paramCache.remove(RC_REQUEST_DRIVE_TO_UPLOAD);
}
private void loginAndRequestDrivePermission(String funid, String account, int requestCode) {
Log.i(TAG, "no drive permission");
Map<String, String> params = Maps.newHashMap();
params.put("funid", funid);
params.put("account", account);
paramCache.put(requestCode, params);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id1))
.requestScopes(new Scope(Scopes.EMAIL), new Scope(DriveScopes.DRIVE_APPDATA))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, requestCode);
}
public void storagePass(String funid, String account, String password) {
Log.i(TAG, "storagePass with: " + account + " | " + password);
Bundle userData = new Bundle();
userData.putString("pass", password);
// save to account manage
runOnUiThread(() -> {
final Account act = new Account(account, accountType);
if (accountManager.addAccountExplicitly(act, password, userData)) {
Log.i(TAG, "storage pass success");
} else {
Log.i(TAG, "storage pass error");
}
});
Log.i(TAG, String.format("storagePass with: %s | %s | %s", funid, account, password));
String filePath;
try {
filePath = WalletUtil.savePassToLocal(this, account, password);
} catch (JSONException | IOException e) {
Log.i(TAG, String.format("error storage pass to local, %s", e.getMessage()));
JcSDK.nativeCb(funid, "error storage pass to local", null);
return;
}
if (!GoogleSignIn.hasPermissions(
GoogleSignIn.getLastSignedInAccount(getActivity()),
new Scope(DriveScopes.DRIVE_APPDATA))) {
loginAndRequestDrivePermission(funid, account, RC_REQUEST_DRIVE_TO_UPLOAD);
} else {
Log.i(TAG, "had drive permission");
WalletUtil.saveToDriveAppFolder(funid, account, JcSDK::nativeCb);
}
// runOnUiThread(() -> {
// Intent intent = new Intent(this, BiometricActivity.class);
// intent.putExtra("action", "encrypt");
@ -927,13 +955,30 @@ public class MainActivity extends UnityPlayerActivity
// startActivity(intent);
// });
}
private void loadDrivePass() {
Map<String, String> params = paramCache.get(RC_REQUEST_DRIVE_TO_READ);
if (params == null) {
return;
}
WalletUtil.downloadCfgToLocal(params.get("funid"), params.get("account"));
WalletUtil.getPassLocal(this, params.get("funid"), params.get("account"));
paramCache.remove(RC_REQUEST_DRIVE_TO_READ);
}
public void authGetStoragePass(String funid, String account) {
Log.i(TAG, "authGetStoragePass with: " + account);
// Account[] accounts = accountManager.getAccountsByType(accountType);
// for (Account act : accounts) {
// Log.i(TAG, "authGetStoragePass account: " + act.name + " | " + act.type );
// }
if (!WalletUtil.localCfgExists(this, account)) {
if (!GoogleSignIn.hasPermissions(
GoogleSignIn.getLastSignedInAccount(getActivity()),
new Scope(DriveScopes.DRIVE_APPDATA))) {
loginAndRequestDrivePermission(funid, account, RC_REQUEST_DRIVE_TO_READ);
} else {
WalletUtil.downloadCfgToLocal(funid, account);
WalletUtil.getPassLocal(this, funid, account);
}
} else {
WalletUtil.getPassLocal(this, funid, account);
}
// runOnUiThread(() -> {
// Intent intent = new Intent(this, BiometricActivity.class);
@ -946,6 +991,5 @@ public class MainActivity extends UnityPlayerActivity
public void getClientId(String funid) {
Log.i(TAG, "getClientId ");
}
}

View File

@ -0,0 +1,138 @@
package com.cege.games.release.wallet;
import android.content.Context;
import android.util.Log;
import com.cege.games.release.MainActivity;
import com.cege.games.release.R;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.common.api.Scope;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.common.base.Strings;
import com.jc.jcfw.JcSDK;
import com.jc.jcfw.NativeResult;
import com.jc.jcfw.security.BiometricResult;
import com.jc.jcfw.util.DriveUtils;
import com.jc.jcfw.util.FileUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.function.Consumer;
public class WalletUtil {
private static final String TAG = WalletUtil.class.getSimpleName();
public static String generateFileName(String account) {
return String.format("wallet_%s.json", account);
}
public static File getWalletCfgFile(Context context, String account) {
String filename = generateFileName(account);
File dic = new File(context.getFilesDir() + "/wallets");
if (!dic.exists()) {
dic.mkdir();
}
return new File(context.getFilesDir() + "/wallets", filename);
}
public static String savePassToLocal(Context context, String account, String pass) throws IOException, JSONException {
File filePath = getWalletCfgFile(context, account);
JSONObject content = new JSONObject();
content.put("pass", pass);
FileUtils.writeFile(filePath, content.toString());
return filePath.getAbsolutePath();
}
public static void getPassLocal(Context context, String funId, String account) {
try {
JSONObject json = loadLocalCfg(context, account);
String passEncrypted = json.getString("pass");
String passDecrypted = JcSDK.decryptPass(account, passEncrypted);
JcSDK.nativeCb(funId, null, passDecrypted);
} catch (JSONException e) {
JcSDK.nativeCb(funId, "error decode json", null);
} catch (IOException e) {
JcSDK.nativeCb(funId, "error read cfg file", null);
}
}
public static boolean localCfgExists(Context context, String account) {
File filePath = getWalletCfgFile(context, account);
return filePath.exists();
}
public static JSONObject loadLocalCfg(Context context, String account) throws JSONException, IOException {
File filePath = getWalletCfgFile(context, account);
if (!filePath.exists()) {
return null;
}
return FileUtils.readJsonFromFile(filePath);
}
public static void saveToDriveAppFolder(String funid, String account, Consumer<NativeResult> func) {
Context context = MainActivity.app;
GoogleSignInAccount ga = GoogleSignIn.getLastSignedInAccount(context);
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context,
Collections.singletonList(DriveScopes.DRIVE_APPDATA));
credential.setSelectedAccount(ga.getAccount());
Drive service = DriveUtils.generateService(credential, context.getString(R.string.app_name));
try {
File file = getWalletCfgFile(MainActivity.app, account);
String fileName = file.getName();
String fileId = DriveUtils.queryOneAppFile(service, fileName);
if (Strings.isNullOrEmpty(fileId)) {
Log.i(TAG, String.format("%s not exists in drive, upload...", fileName));
fileId = DriveUtils.uploadAppFile(service, file, "application/json");
}
Log.i(TAG, "File ID: " + fileId);
func.accept(new NativeResult(funid, null, fileId));
} catch (GoogleJsonResponseException e) {
Log.i(TAG, "Unable to create file: " + e.getDetails());
func.accept(new NativeResult(funid, e.getMessage(), null));
} catch (IOException e) {
Log.i(TAG, e.getMessage());
func.accept(new NativeResult(funid, e.getMessage(), null));
}
}
public static void downloadCfgToLocal(String funid, String account) {
Context context = MainActivity.app;
GoogleSignInAccount ga = GoogleSignIn.getLastSignedInAccount(context);
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context,
Collections.singletonList(DriveScopes.DRIVE_APPDATA));
credential.setSelectedAccount(ga.getAccount());
Drive service = DriveUtils.generateService(credential, context.getString(R.string.app_name));
String fileName = generateFileName(account);
String fileId = DriveUtils.queryOneAppFile(service, fileName);
if (Strings.isNullOrEmpty(fileId)) {
Log.i(TAG, "file not found in drive");
return;
}
boolean downloadSuccess = false;
while (!downloadSuccess) {
try {
String jsonStr = DriveUtils.downloadFile(service, fileId);
File fileLocal = getWalletCfgFile(context, account);
FileUtils.writeFile(fileLocal, jsonStr);
downloadSuccess = true;
} catch (IOException e) {
Log.i(TAG, "error download file");
}
}
}
}

View File

@ -7,7 +7,9 @@ import android.net.Uri;
import android.util.Log;
import com.cege.games.release.MainActivity;
import com.google.common.base.Strings;
import com.jc.jcfw.google.PayClient;
import com.jc.jcfw.util.ThreadUtils;
import org.cocos2dx.lib.CocosJSHelper;
import org.json.JSONException;
@ -27,6 +29,8 @@ public class JcSDK {
private static native int runJS(final String funId, final String methodName, final String params);
public static native String decryptPass(final String account, final String pass);
public static void initCommonCB(UnityCallback callBack) {
Log.i(TAG, "call init common callback from unity");
commonCB = callBack;
@ -174,18 +178,15 @@ public class JcSDK {
MainActivity.app.getClientId(funid);
}
/**
* 回调至js
*/
public static void nativeCb(String funId, String error, String dataStr) {
JSONObject result = new JSONObject();
try {
if (error != null && !error.isEmpty()) {
result.put("errcode", 1);
result.put("errmessage", error);
} else {
if (Strings.isNullOrEmpty(error)) {
result.put("errcode", 0);
result.put("data", dataStr);
} else {
result.put("errcode", 1);
result.put("errmessage", error);
}
} catch (JSONException e) {
Log.e(TAG, "JSONException: " + e.getMessage());
@ -193,6 +194,17 @@ public class JcSDK {
if (funId == null || funId.isEmpty()) {
funId = MainActivity.app.getFunId();
}
JcSDK.runJS(funId, "jniCallback", result.toString());
Log.i(TAG, String.format("%s native cb, error: %s, data: %s", funId, error, dataStr ));
if (ThreadUtils.isMainThread()) {
JcSDK.runJS(funId, "jniCallback", result.toString());
} else {
String finalFunId = funId;
MainActivity.app.runOnUiThread(() -> JcSDK.runJS(finalFunId, "jniCallback", result.toString()));
}
}
public static void nativeCb(NativeResult result) {
nativeCb(result.getFunid(), result.getError(), result.getDataStr());
}
}

View File

@ -0,0 +1,37 @@
package com.jc.jcfw;
public class NativeResult {
private String funid;
private String error;
private String dataStr;
public NativeResult(String funid, String error, String dataStr) {
this.funid = funid;
this.error = error;
this.dataStr = dataStr;
}
public String getFunid() {
return funid;
}
public void setFunid(String funid) {
this.funid = funid;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getDataStr() {
return dataStr;
}
public void setDataStr(String dataStr) {
this.dataStr = dataStr;
}
}

View File

@ -0,0 +1,101 @@
package com.jc.jcfw.util;
import android.util.Log;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.http.FileContent;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.function.Consumer;
public class DriveUtils {
private static final String TAG = DriveUtils.class.getSimpleName();
public static Drive generateService(GoogleAccountCredential credential, String appName) {
return new Drive.Builder(
AndroidHttp.newCompatibleTransport(),
AndroidJsonFactory.getDefaultInstance(),
credential)
.setApplicationName(appName)
.build();
}
/**
* query app file by filename
*
* @param service
* @param fileName
* @throws IOException
*/
public static String queryOneAppFile(Drive service, String fileName) {
boolean querySuccess = false;
String fileId = "";
while (!querySuccess) {
try {
FileList files = service.files().list()
.setSpaces("appDataFolder")
.setFields("nextPageToken, files(id, name)")
.setPageSize(100)
.execute();
querySuccess = true;
for (File file : files.getFiles()) {
Log.i(TAG, String.format("Found file: %s (%s)\n", file.getName(), file.getId()));
if (file.getName().equals(fileName)) {
fileId = file.getId();
break;
}
}
} catch (IOException e) {
Log.i(TAG, "error query file from drive");
}
}
return fileId;
}
/**
* download one file from drive
*
* @param service
* @param fileId
* @throws IOException
*/
public static String downloadFile(Drive service, String fileId) throws IOException {
OutputStream outputStream = new ByteArrayOutputStream();
service.files().get(fileId).executeMediaAndDownloadTo(outputStream);
// convert outputStream to JSON string
// String json = outputStream.toString();
return outputStream.toString();
}
/**
* upload one file to Drive
*
* @param service
* @param filePath file absolute path
* @param fileType application/json
* @throws IOException
*/
public static String uploadAppFile(Drive service, java.io.File filePath, String fileType) throws IOException {
String fileName = filePath.getName();
File fileMetadata = new File();
fileMetadata.setName(fileName);
fileMetadata.setParents(Collections.singletonList("appDataFolder"));
// "application/json"
FileContent mediaContent = new FileContent(fileType, filePath);
File file = service.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
Log.i(TAG, String.format("%s upload success, File ID: %s", fileName, file.getId()));
return file.getId();
}
}

View File

@ -13,10 +13,15 @@ import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class FileUtils {
private static final String TAG = FileUtils.class.getSimpleName();
@ -26,7 +31,7 @@ public class FileUtils {
* @param fileName path
* @return TRUE or FALSE
*/
static boolean fileIsExist(String fileName) {
public static boolean fileIsExist(String fileName) {
File file = new File(fileName);
if (file.exists())
return true;
@ -35,6 +40,20 @@ public class FileUtils {
}
}
public static void writeFile(File filePath, String content) throws IOException {
FileOutputStream out = new FileOutputStream(filePath);
out.write(content.getBytes());
out.close();
}
public static JSONObject readJsonFromFile(File filePath) throws IOException, JSONException {
RandomAccessFile f = new RandomAccessFile(filePath, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new JSONObject(new String(bytes));
}
/**
* get image base path of external storage
*/

View File

@ -9,7 +9,8 @@ import android.util.Log;
import androidx.annotation.Nullable;
import com.cege.games.release.MainActivity;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
@ -20,7 +21,7 @@ import java.util.UUID;
public class IDUtils {
private static String sID = null;
private static final String WALLET_STATS = "wallets";
private static final String WALLET_STATS = "wallet.json";
public synchronized static String id(Context context) {
if (sID == null) {
@ -37,18 +38,23 @@ public class IDUtils {
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
private static String readInstallationFile(File installation) throws IOException, JSONException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
String jsonStr = new String(bytes);
Log.i("IDUtils", jsonStr);
JSONObject content = new JSONObject(new String(bytes));
return content.getString("id");
}
private static void writeInstallationFile(File installation) throws IOException {
private static void writeInstallationFile(File installation) throws IOException, JSONException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
JSONObject content = new JSONObject();
content.put("id", id);
out.write(content.toString().getBytes());
out.close();
}

View File

@ -0,0 +1,14 @@
package com.jc.jcfw.util;
import android.os.Looper;
public class ThreadUtils {
/**
* check if current thread is main thread
*
* @return
*/
public static boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
}

12
res/raw/apple_config.json Normal file
View File

@ -0,0 +1,12 @@
{
"client_id": "wallet.cebggame.com",
"redirect_uri": "https://wallet.cebggame.com/apple/oauth_redirect",
"end_session_redirect_uri": "com.apple.apps.wallet.cebggame.com:/oauth2redirect",
"authorization_scope": "name email",
"discovery_uri": "https://appleid.apple.com/.well-known/openid-configuration",
"authorization_endpoint_uri": "",
"token_endpoint_uri": "",
"registration_endpoint_uri": "",
"user_info_endpoint_uri": "",
"https_required": true
}