add download drive file with none google play service

This commit is contained in:
CounterFire2023 2023-09-05 17:37:04 +08:00
parent c7a74b07d0
commit 442d2efa60
6 changed files with 232 additions and 65 deletions

View File

@ -137,10 +137,27 @@
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.googleusercontent.apps.53206975661-ih3r0ubph3rqejdq97b029difbrk2bqj" />
<data android:scheme="com.googleusercontent.apps.53206975661-asnf3qe4bg29p8h981pgf099osvrjbme" /> <data android:scheme="com.googleusercontent.apps.53206975661-asnf3qe4bg29p8h981pgf099osvrjbme" />
<data android:scheme="cebg" android:path="/apple_login_result" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data
android:host="oauth-svr.cebggame.com"
android:pathPrefix="/google" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data
android:host="oauth-svr.cebggame.com"
android:pathPrefix="/google" />
</intent-filter>
</activity> </activity>
<activity <activity
android:name=".tiktokapi.TikTokEntryActivity" android:name=".tiktokapi.TikTokEntryActivity"
@ -150,20 +167,20 @@
<activity <activity
android:name=".apple.AppleLoginActivity" android:name=".apple.AppleLoginActivity"
android:theme="@style/WebViewTheme" /> android:theme="@style/WebViewTheme" />
<!-- <activity--> <activity
<!-- android:name=".apple.AppleLoginCbActivity"--> android:name=".apple.AppleLoginCbActivity"
<!-- android:exported="true">--> android:exported="true">
<!-- <intent-filter>--> <intent-filter>
<!-- <action android:name="android.intent.action.VIEW" />--> <action android:name="android.intent.action.VIEW" />
<!-- <category android:name="android.intent.category.DEFAULT" />--> <category android:name="android.intent.category.DEFAULT" />
<!-- <category android:name="android.intent.category.BROWSABLE" />--> <category android:name="android.intent.category.BROWSABLE" />
<!-- <data--> <data
<!-- android:scheme="cebg"--> android:scheme="cebg"
<!-- android:path="/apple_login_result" />--> android:path="/apple_login_result" />
<!-- </intent-filter>--> </intent-filter>
<!-- </activity>--> </activity>
<activity <activity
android:name="com.facebook.FacebookActivity" android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"

View File

@ -167,14 +167,13 @@ dependencies {
implementation 'com.github.jenly1314:zxing-lite:2.1.1' implementation 'com.github.jenly1314:zxing-lite:2.1.1'
implementation 'net.openid:appauth:0.11.1' implementation 'net.openid:appauth:0.11.1'
implementation "com.squareup.okio:okio:2.10.0" implementation "com.squareup.okio:okio:2.10.0"
implementation 'com.android.volley:volley:1.2.1'
implementation 'org.greenrobot:eventbus:3.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.bytedance.ies.ugc.aweme:opensdk-oversea-external:0.2.1.0' implementation 'com.bytedance.ies.ugc.aweme:opensdk-oversea-external:0.2.1.0'
implementation 'com.google.android.play:core:1.10.0' //PAD资源分发 implementation 'com.google.android.play:core:1.10.0' //PAD资源分发
implementation 'com.facebook.android:facebook-core:latest.release' implementation 'com.facebook.android:facebook-core:latest.release'
implementation 'com.facebook.android:facebook-login:latest.release' implementation 'com.facebook.android:facebook-login:latest.release'
implementation 'com.facebook.android:facebook-share:latest.release' implementation 'com.facebook.android:facebook-share:latest.release'
implementation "com.squareup.okhttp3:okhttp:4.10.0"
// begin of firebase // begin of firebase
implementation platform('com.google.firebase:firebase-bom:32.1.1') implementation platform('com.google.firebase:firebase-bom:32.1.1')
implementation 'com.google.firebase:firebase-analytics' implementation 'com.google.firebase:firebase-analytics'

View File

@ -1,5 +1,6 @@
package com.cege.games.release; package com.cege.games.release;
import static net.openid.appauth.AuthorizationResponse.TOKEN_TYPE_BEARER;
import static org.cocos2dx.lib.Cocos2dxHelper.getActivity; import static org.cocos2dx.lib.Cocos2dxHelper.getActivity;
import android.Manifest; import android.Manifest;
@ -93,10 +94,12 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import pub.devrel.easypermissions.AfterPermissionGranted; import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions; import pub.devrel.easypermissions.EasyPermissions;
@ -160,6 +163,14 @@ public class MainActivity extends UnityPlayerActivity
// store params for request permission or jump to other activity // store params for request permission or jump to other activity
private final Map<Integer, Map<String, String>> paramCache = Maps.newHashMap(); private final Map<Integer, Map<String, String>> paramCache = Maps.newHashMap();
private Consumer<String> nextAction = null;
public boolean isGooglePlayServicesAvailable() {
// return
// GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) ==
// ConnectionResult.SUCCESS;
return false;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -224,7 +235,6 @@ public class MainActivity extends UnityPlayerActivity
if (response != null || ex != null) { if (response != null || ex != null) {
mAuthStateManager.updateAfterAuthorization(response, ex); mAuthStateManager.updateAfterAuthorization(response, ex);
} }
if (response != null && response.authorizationCode != null) { if (response != null && response.authorizationCode != null) {
// authorization code exchange is required // authorization code exchange is required
mAuthStateManager.updateAfterAuthorization(response, ex); mAuthStateManager.updateAfterAuthorization(response, ex);
@ -236,12 +246,10 @@ public class MainActivity extends UnityPlayerActivity
} }
break; break;
case RC_SIGN_IN: case RC_SIGN_IN:
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); handleSignInResult(GoogleSignIn.getSignedInAccountFromIntent(data));
handleSignInResult(task);
break; break;
case FILE_SELECTOR_CODE: case FILE_SELECTOR_CODE:
Uri uri = data.getData(); shareToTikTok(funId, data.getData());
shareToTikTok(funId, uri);
break; break;
case RC_REQUEST_DRIVE_TO_UPLOAD: case RC_REQUEST_DRIVE_TO_UPLOAD:
mExecutor.submit(this::saveToDriveAppFolder); mExecutor.submit(this::saveToDriveAppFolder);
@ -418,7 +426,7 @@ public class MainActivity extends UnityPlayerActivity
// end of qrcode // end of qrcode
public void signWithGoogle(String funId) { public void signWithGoogle(String funId) {
this.funId = funId; this.funId = funId;
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) { if (isGooglePlayServicesAvailable()) {
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) { if (account != null) {
Log.w(TAG, "already login: " + account.getIdToken()); Log.w(TAG, "already login: " + account.getIdToken());
@ -429,22 +437,18 @@ public class MainActivity extends UnityPlayerActivity
startActivityForResult(signInIntent, RC_SIGN_IN); startActivityForResult(signInIntent, RC_SIGN_IN);
} }
} else { } else {
// Log.i(TAG, "no gms, use app auth"); Log.d(TAG, "no gms, use app auth");
AuthState state = mAuthStateManager.getCurrent(); AuthState state = mAuthStateManager.getCurrent();
if (state.isAuthorized() && state.getIdToken() != null) { if (state.isAuthorized()) {
Log.w(TAG, "getNeedsTokenRefresh: " + state.getNeedsTokenRefresh());
if (state.getNeedsTokenRefresh()) { if (state.getNeedsTokenRefresh()) {
Log.w(TAG, "need refresh accessToken"); Log.w(TAG, "need refresh accessToken");
TokenRequest tokenRequest = state.createTokenRefreshRequest(); performTokenRequest(state.createTokenRefreshRequest(), this::handleCodeExchangeResponse);
performTokenRequest(
tokenRequest,
this::handleCodeExchangeResponse);
} else { } else {
Log.w(TAG, "already login, accessToken not expired"); Log.w(TAG, "already login, accessToken not expired, id token:: " + state.getIdToken());
Log.w(TAG, "id token : " + state.getIdToken());
JcSDK.nativeCb(this.funId, null, state.getIdToken()); JcSDK.nativeCb(this.funId, null, state.getIdToken());
} }
} else { } else {
Log.w(TAG, "not login");
mExecutor.submit(this::doAuth); mExecutor.submit(this::doAuth);
} }
} }
@ -556,14 +560,12 @@ public class MainActivity extends UnityPlayerActivity
ResponseTypeValues.CODE, ResponseTypeValues.CODE,
mConfiguration.getRedirectUri()) mConfiguration.getRedirectUri())
// apple need `form_post` when authorization_scope has `name email ` // apple need `form_post` when authorization_scope has `name email `
// .setResponseMode("form_post") // .setResponseMode("form_post")
// .setResponseType("code id_token") // .setResponseType("code id_token")
.setScope(mConfiguration.getScope()); .setScope(mConfiguration.getScope());
if (!TextUtils.isEmpty(loginHint)) { if (!TextUtils.isEmpty(loginHint)) {
authRequestBuilder.setLoginHint(loginHint); authRequestBuilder.setLoginHint(loginHint);
} }
mAuthRequest.set(authRequestBuilder.build()); mAuthRequest.set(authRequestBuilder.build());
} }
@ -571,7 +573,9 @@ public class MainActivity extends UnityPlayerActivity
mAuthIntentLatch = new CountDownLatch(1); mAuthIntentLatch = new CountDownLatch(1);
mExecutor.execute(() -> { mExecutor.execute(() -> {
Log.i(TAG, "Warming up browser instance for auth request"); Log.i(TAG, "Warming up browser instance for auth request");
CustomTabsIntent.Builder intentBuilder = mAuthService.createCustomTabsIntentBuilder(mAuthRequest.get().toUri()); Uri uri = mAuthRequest.get().toUri();
Log.i(TAG, "URI: " + uri);
CustomTabsIntent.Builder intentBuilder = mAuthService.createCustomTabsIntentBuilder(uri);
mAuthIntent.set(intentBuilder.build()); mAuthIntent.set(intentBuilder.build());
mAuthIntentLatch.countDown(); mAuthIntentLatch.countDown();
}); });
@ -706,25 +710,27 @@ public class MainActivity extends UnityPlayerActivity
callback); callback);
} }
private void checkAuthStateAndCB() {
AuthState state = mAuthStateManager.getCurrent();
Log.d(TAG, "login success, auth state: " + state.isAuthorized());
Log.d(TAG, "id token : " + state.getIdToken());
Log.d(TAG, "access token: " + state.getAccessToken());
Log.d(TAG, "refresh token: " + state.getRefreshToken());
mAuthStateManager.replace(state);
JcSDK.nativeCb(this.funId, null, state.getIdToken());
}
@WorkerThread @WorkerThread
private void handleCodeExchangeResponse( private void handleCodeExchangeResponse(
@Nullable TokenResponse tokenResponse, @Nullable TokenResponse tokenResponse,
@Nullable AuthorizationException authException) { @Nullable AuthorizationException authException) {
mAuthStateManager.updateAfterTokenResponse(tokenResponse, authException); mAuthStateManager.updateAfterTokenResponse(tokenResponse, authException);
if (!mAuthStateManager.getCurrent().isAuthorized()) { if (!mAuthStateManager.getCurrent().isAuthorized()) {
final String message = "Authorization Code exchange failed" final String message = "Authorization Code exchange failed: "
+ ((authException != null) ? authException.error : ""); + ((authException != null) ? authException.error : "");
// WrongThread inference is incorrect for lambdas
// noinspection WrongThread
Log.d(TAG, message); Log.d(TAG, message);
} else { } else {
AuthState state = mAuthStateManager.getCurrent(); checkAuthStateAndCB();
Log.d(TAG, "login success, auth state: " + state.isAuthorized());
Log.d(TAG, "app auth idToken: " + state.getIdToken());
mAuthStateManager.replace(state);
JcSDK.nativeCb(this.funId, null, state.getIdToken());
} }
} }
@ -803,7 +809,7 @@ public class MainActivity extends UnityPlayerActivity
public void shareWithFacebook(String content) { public void shareWithFacebook(String content) {
ShareLinkContent linkContent = new ShareLinkContent.Builder() ShareLinkContent linkContent = new ShareLinkContent.Builder()
.setContentUrl(Uri.parse("https://www.baidu.com")) .setContentUrl(Uri.parse("https://www.google.com"))
.setQuote(content) .setQuote(content)
.build(); .build();
ShareDialog.show(this, linkContent); ShareDialog.show(this, linkContent);
@ -904,6 +910,7 @@ public class MainActivity extends UnityPlayerActivity
Log.i(TAG, "passStorageState with: " + account); Log.i(TAG, "passStorageState with: " + account);
} }
@WorkerThread
private void saveToDriveAppFolder() { private void saveToDriveAppFolder() {
Map<String, String> params = paramCache.get(RC_REQUEST_DRIVE_TO_UPLOAD); Map<String, String> params = paramCache.get(RC_REQUEST_DRIVE_TO_UPLOAD);
if (params == null) { if (params == null) {
@ -927,11 +934,11 @@ public class MainActivity extends UnityPlayerActivity
Intent signInIntent = mGoogleSignInClient.getSignInIntent(); Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, requestCode); startActivityForResult(signInIntent, requestCode);
} }
public void storagePass(String funid, String account, String password) { public void storagePass(String funid, String account, String password) {
Log.i(TAG, String.format("storagePass with: %s | %s | %s", funid, account, password)); Log.i(TAG, String.format("storagePass with: %s | %s", funid, account));
String filePath;
try { try {
filePath = WalletUtil.savePassToLocal(this, account, password); WalletUtil.savePassToLocal(this, account, password);
} catch (JSONException | IOException e) { } catch (JSONException | IOException e) {
Log.i(TAG, String.format("error storage pass to local, %s", e.getMessage())); Log.i(TAG, String.format("error storage pass to local, %s", e.getMessage()));
JcSDK.nativeCb(funid, "error storage pass to local", null); JcSDK.nativeCb(funid, "error storage pass to local", null);
@ -955,6 +962,8 @@ public class MainActivity extends UnityPlayerActivity
// startActivity(intent); // startActivity(intent);
// }); // });
} }
@WorkerThread
private void loadDrivePass() { private void loadDrivePass() {
Map<String, String> params = paramCache.get(RC_REQUEST_DRIVE_TO_READ); Map<String, String> params = paramCache.get(RC_REQUEST_DRIVE_TO_READ);
if (params == null) { if (params == null) {
@ -964,8 +973,10 @@ public class MainActivity extends UnityPlayerActivity
WalletUtil.getPassLocal(this, params.get("funid"), params.get("account")); WalletUtil.getPassLocal(this, params.get("funid"), params.get("account"));
paramCache.remove(RC_REQUEST_DRIVE_TO_READ); paramCache.remove(RC_REQUEST_DRIVE_TO_READ);
} }
public void authGetStoragePass(String funid, String account) { public void authGetStoragePass(String funid, String account) {
Log.i(TAG, "authGetStoragePass with: " + account); Log.i(TAG, "authGetStoragePass with: " + account);
if (isGooglePlayServicesAvailable()) {
if (!WalletUtil.localCfgExists(this, account)) { if (!WalletUtil.localCfgExists(this, account)) {
if (!GoogleSignIn.hasPermissions( if (!GoogleSignIn.hasPermissions(
GoogleSignIn.getLastSignedInAccount(getActivity()), GoogleSignIn.getLastSignedInAccount(getActivity()),
@ -978,7 +989,35 @@ public class MainActivity extends UnityPlayerActivity
} else { } else {
WalletUtil.getPassLocal(this, funid, account); WalletUtil.getPassLocal(this, funid, account);
} }
} else {
if (!WalletUtil.localCfgExists(this, account)) {
AuthState state = mAuthStateManager.getCurrent();
WalletUtil.downloadCfgWithApi(funid, account, state.getAccessToken());
WalletUtil.getPassLocal(this, funid, account);
// TODO::
// 1. check whether the google account has been logged in, this situation occurs
// when non-google login
// 2. check if already had permission of drive appdata, add permission of drive
// appdata to auth_config
// 3. check if need refresh access token
// if (state.isAuthorized()) {
// if (state.getNeedsTokenRefresh()) {
// Log.d(TAG, "need refresh accessToken");
// performTokenRequest(state.createTokenRefreshRequest(),
// this::handleCodeExchangeResponse);
// } else {
// Log.d(TAG, "access token no need refresh");
// WalletUtil.downloadCfgToLocal(funid, account);
// WalletUtil.getPassLocal(this, funid, account);
// }
// } else {
// Log.w(TAG, "not login");
// mExecutor.submit(this::doAuth);
// }
} else {
WalletUtil.getPassLocal(this, funid, account);
}
}
// runOnUiThread(() -> { // runOnUiThread(() -> {
// Intent intent = new Intent(this, BiometricActivity.class); // Intent intent = new Intent(this, BiometricActivity.class);

View File

@ -17,6 +17,7 @@ import com.jc.jcfw.JcSDK;
import com.jc.jcfw.NativeResult; import com.jc.jcfw.NativeResult;
import com.jc.jcfw.security.BiometricResult; import com.jc.jcfw.security.BiometricResult;
import com.jc.jcfw.util.DriveUtils; import com.jc.jcfw.util.DriveUtils;
import com.jc.jcfw.util.DriverApiUtils;
import com.jc.jcfw.util.FileUtils; import com.jc.jcfw.util.FileUtils;
import org.json.JSONException; import org.json.JSONException;
@ -114,13 +115,13 @@ public class WalletUtil {
String fileName = generateFileName(account); String fileName = generateFileName(account);
String fileId = DriveUtils.queryOneAppFile(service, fileName); String fileId = DriveUtils.queryOneAppFile(service, fileName);
if (Strings.isNullOrEmpty(fileId)) { if (Strings.isNullOrEmpty(fileId)) {
Log.i(TAG, "file not found in drive"); Log.i(TAG, "file not found in drive");
return; return;
} }
boolean downloadSuccess = false; boolean downloadSuccess = false;
while (!downloadSuccess) { int count = 0;
while (!downloadSuccess && count++ < 10) {
try { try {
String jsonStr = DriveUtils.downloadFile(service, fileId); String jsonStr = DriveUtils.downloadFile(service, fileId);
File fileLocal = getWalletCfgFile(context, account); File fileLocal = getWalletCfgFile(context, account);
@ -130,9 +131,23 @@ public class WalletUtil {
Log.i(TAG, "error download file"); Log.i(TAG, "error download file");
} }
} }
} }
public static void downloadCfgWithApi(String funid, String account, String accesToken) {
Context context = MainActivity.app;
DriverApiUtils api = new DriverApiUtils(accesToken);
String fileName = generateFileName(account);
try {
String fileId = api.queryOneAppFile(fileName);
if (Strings.isNullOrEmpty(fileId)) {
Log.i(TAG, "file not found in drive");
return;
}
String jsonStr = api.fileInfo(fileId);
File fileLocal = getWalletCfgFile(context, account);
FileUtils.writeFile(fileLocal, jsonStr);
} catch (IOException | JSONException e) {
Log.i(TAG, "error download file");
}
}
} }

View File

@ -164,12 +164,10 @@ public class JcSDK {
} }
public static void storagePass(String funid, String account, String password) { public static void storagePass(String funid, String account, String password) {
Log.i(TAG, "storagePass with: " + account);
MainActivity.app.storagePass(funid, account, password); MainActivity.app.storagePass(funid, account, password);
} }
public static void authGetStoragePass(String funid, String account) { public static void authGetStoragePass(String funid, String account) {
Log.i(TAG, "authGetStoragePass with: " + account);
MainActivity.app.authGetStoragePass(funid, account); MainActivity.app.authGetStoragePass(funid, account);
} }

View File

@ -0,0 +1,99 @@
package com.jc.jcfw.util;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class DriverApiUtils {
private static final String driveApiBase = "https://www.googleapis.com/drive/v3/files";
private final String TAG = getClass().getSimpleName();
private String token = "";
public DriverApiUtils() {
}
public DriverApiUtils(String token) {
this.token = token;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public JSONArray fileList() throws IOException, JSONException {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
Request request = new Request.Builder()
.url(driveApiBase + "?spaces=appDataFolder&fields=files(id, name, modifiedTime)")
.get()
.addHeader("Authorization", "Bearer " + token)
.build();
try (Response response = client.newCall(request).execute()) {
String resStr = response.body().string();
JSONObject resJson = new JSONObject(resStr);
return resJson.getJSONArray("files");
}
}
public String queryOneAppFile(String fileName) throws IOException, JSONException {
JSONArray fileList = fileList();
for (int i = 0; i < fileList.length(); i++) {
JSONObject file = fileList.getJSONObject(i);
if (file.getString("name").equals(fileName)) {
return file.getString("id");
}
}
return "";
}
public String fileInfo(String fileId) throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
Request request = new Request.Builder()
.url(String.format("%s/%s?alt=media", driveApiBase, fileId))
.get()
.addHeader("Authorization", "Bearer " + token)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
public void createFile() throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("", "upload-options.json",
RequestBody.create(MediaType.parse("application/octet-stream"),
new File("/Users/zhl/Desktop/drivetest/files/upload-options.json")))
.addFormDataPart("", "wallet_1.json",
RequestBody.create(MediaType.parse("application/octet-stream"),
new File("/Users/zhl/Desktop/drivetest/files/wallet_1.json")))
.build();
Request request = new Request.Builder()
.url(driveApiBase + "?uploadType=multipart")
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer " + token)
.build();
Response response = client.newCall(request).execute();
}
}