841 lines
28 KiB
Java
841 lines
28 KiB
Java
package com.cege.games.release;
|
|
|
|
import android.Manifest;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.pm.ApplicationInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.graphics.Bitmap;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.provider.MediaStore;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.view.Window;
|
|
import android.widget.Toast;
|
|
|
|
import com.bytedance.sdk.open.tiktok.TikTokOpenApiFactory;
|
|
import com.bytedance.sdk.open.tiktok.api.TikTokOpenApi;
|
|
import com.bytedance.sdk.open.tiktok.authorize.model.Authorization;
|
|
import com.cege.games.release.activity.CustomCaptureActivity;
|
|
import com.cege.games.release.dialog.QRCodeActivity;
|
|
import com.facebook.AccessToken;
|
|
import com.facebook.CallbackManager;
|
|
import com.facebook.FacebookCallback;
|
|
import com.facebook.FacebookException;
|
|
|
|
import com.facebook.login.LoginManager;
|
|
import com.facebook.login.LoginResult;
|
|
import com.facebook.share.model.ShareLinkContent;
|
|
import com.facebook.share.widget.ShareDialog;
|
|
import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
|
|
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
|
|
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
|
|
import com.google.android.gms.common.ConnectionResult;
|
|
import com.google.android.gms.common.GoogleApiAvailability;
|
|
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.jc.jcfw.JcSDK;
|
|
import com.jc.jcfw.appauth.AuthStateManager;
|
|
import com.jc.jcfw.appauth.JConfiguration;
|
|
import com.jc.jcfw.util.FileUtils;
|
|
import com.king.zxing.CameraScan;
|
|
import com.king.zxing.util.CodeUtils;
|
|
import com.king.zxing.util.LogUtils;
|
|
import com.unity3d.player.UnityPlayerActivity;
|
|
|
|
import net.openid.appauth.AppAuthConfiguration;
|
|
import net.openid.appauth.AuthState;
|
|
import net.openid.appauth.AuthorizationException;
|
|
import net.openid.appauth.AuthorizationRequest;
|
|
import net.openid.appauth.AuthorizationResponse;
|
|
import net.openid.appauth.AuthorizationService;
|
|
import net.openid.appauth.AuthorizationServiceConfiguration;
|
|
import net.openid.appauth.ClientAuthentication;
|
|
import net.openid.appauth.ClientSecretBasic;
|
|
import net.openid.appauth.RegistrationRequest;
|
|
import net.openid.appauth.RegistrationResponse;
|
|
import net.openid.appauth.ResponseTypeValues;
|
|
import net.openid.appauth.TokenRequest;
|
|
import net.openid.appauth.TokenResponse;
|
|
import net.openid.appauth.browser.AnyBrowserMatcher;
|
|
import net.openid.appauth.browser.BrowserMatcher;
|
|
|
|
import org.cocos2dx.lib.Cocos2dxHelper;
|
|
import org.cocos2dx.lib.CocosJSHelper;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.concurrent.CountDownLatch;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
import androidx.annotation.MainThread;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.WorkerThread;
|
|
import androidx.browser.customtabs.CustomTabsIntent;
|
|
import androidx.core.app.ActivityOptionsCompat;
|
|
import pub.devrel.easypermissions.AfterPermissionGranted;
|
|
import pub.devrel.easypermissions.EasyPermissions;
|
|
|
|
import static com.cege.games.release.dialog.QRCodeActivity.RC_SAVE_QR;
|
|
|
|
public class MainActivity extends UnityPlayerActivity
|
|
implements Cocos2dxHelper.Cocos2dxHelperListener, EasyPermissions.PermissionCallbacks {
|
|
private static final String TAG = MainActivity.class.getSimpleName();
|
|
|
|
public static MainActivity app;
|
|
private Toast toast;
|
|
|
|
public static final String KEY_TITLE = "key_title";
|
|
public static final String KEY_IS_QR_CODE = "key_code";
|
|
public static final String KEY_IS_CONTINUOUS = "key_continuous_scan";
|
|
|
|
// scan QRCode
|
|
public static final int REQUEST_CODE_SCAN = 0X01;
|
|
public static final int REQUEST_CODE_PHOTO = 0X02;
|
|
// AppAuth
|
|
private static final int RC_AUTH = 0X04;
|
|
// google signin
|
|
private static final int RC_SIGN_IN = 0X05;
|
|
|
|
public static final int RC_CAMERA = 0X011;
|
|
|
|
public static final int RC_READ_PHOTO = 0X012;
|
|
|
|
public static final int RC_LOAD_KEY = 0X013;
|
|
private String title;
|
|
private String funId;
|
|
private String oid;
|
|
|
|
private QRCodeActivity qrCodeActivity;
|
|
|
|
//AppAuth
|
|
private AuthorizationService mAuthService;
|
|
private AuthStateManager mAuthStateManager;
|
|
private JConfiguration mConfiguration;
|
|
private ExecutorService mExecutor;
|
|
private final AtomicReference<String> mClientId = new AtomicReference<>();
|
|
private final AtomicReference<AuthorizationRequest> mAuthRequest = new AtomicReference<>();
|
|
private final AtomicReference<CustomTabsIntent> mAuthIntent = new AtomicReference<>();
|
|
private CountDownLatch mAuthIntentLatch = new CountDownLatch(1);
|
|
private static final String EXTRA_FAILED = "failed";
|
|
|
|
public String getFunId() {
|
|
return funId;
|
|
}
|
|
|
|
@NonNull
|
|
private final BrowserMatcher mBrowserMatcher = AnyBrowserMatcher.INSTANCE;
|
|
|
|
private GoogleSignInClient mGoogleSignInClient;
|
|
// facebook login
|
|
private CallbackManager mCallbackManager;
|
|
|
|
protected String updateUnityCommandLineArguments(String cmdLine) {
|
|
return cmdLine;
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
super.onCreate(savedInstanceState);
|
|
Log.i(TAG, "onCreate: " + getIntent().getDataString());
|
|
|
|
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
|
|
getIntent().putExtra("unity", cmdLine);
|
|
|
|
onLoadNativeLibraries();
|
|
app = this;
|
|
Cocos2dxHelper.init(this);
|
|
CocosJSHelper.initJSEnv(getApplicationContext());
|
|
|
|
// begin of google sign
|
|
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
|
.requestIdToken(getString(R.string.default_web_client_id))
|
|
.requestScopes(new Scope(Scopes.EMAIL))
|
|
// .requestScopes(new Scope("https://www.googleapis.com/auth/drive.appdata"))
|
|
.build();
|
|
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
|
|
// end of google sign
|
|
|
|
// begin of google oauth sign
|
|
mExecutor = Executors.newSingleThreadExecutor();
|
|
mAuthStateManager = AuthStateManager.getInstance(this);
|
|
mConfiguration = JConfiguration.getInstance(this);
|
|
mExecutor.submit(this::initializeAppAuth);
|
|
// end of google oauth sign
|
|
|
|
// begin of facebook login
|
|
initFacebookSDK();
|
|
// end of facebook login
|
|
}
|
|
|
|
@Override
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
mCallbackManager.onActivityResult(requestCode, resultCode, data);
|
|
if(resultCode == RESULT_OK && data!=null){
|
|
switch (requestCode){
|
|
case REQUEST_CODE_SCAN:
|
|
String result = CameraScan.parseScanResult(data);
|
|
Log.i(TAG, "scan qrcode with funId: " +funId+ " result: " + result);
|
|
JcSDK.scanQrCb(funId, null, result);
|
|
funId = "";
|
|
break;
|
|
case REQUEST_CODE_PHOTO:
|
|
parsePhoto(data);
|
|
break;
|
|
case RC_AUTH:
|
|
AuthorizationResponse response = AuthorizationResponse.fromIntent(data);
|
|
AuthorizationException ex = AuthorizationException.fromIntent(data);
|
|
if (response != null || ex != null) {
|
|
mAuthStateManager.updateAfterAuthorization(response, ex);
|
|
}
|
|
|
|
if (response != null && response.authorizationCode != null) {
|
|
// authorization code exchange is required
|
|
mAuthStateManager.updateAfterAuthorization(response, ex);
|
|
exchangeAuthorizationCode(response);
|
|
} else if (ex != null) {
|
|
Log.i(TAG, "Authorization flow failed: " + ex.getMessage());
|
|
} else {
|
|
Log.i(TAG, "No authorization state retained - reauthorization required");
|
|
}
|
|
break;
|
|
case RC_SIGN_IN:
|
|
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
|
|
handleSignInResult(task);
|
|
break;
|
|
}
|
|
} else {
|
|
boolean next = false;
|
|
if (requestCode == REQUEST_CODE_SCAN && data != null) {
|
|
if (data.getBooleanExtra("localImg", false)) {
|
|
startPhotoCode(this.funId);
|
|
next = true;
|
|
}
|
|
}
|
|
if (!next) {
|
|
if (requestCode == RC_SIGN_IN) {
|
|
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
|
|
handleSignInResult(task);
|
|
}
|
|
if (requestCode == REQUEST_CODE_SCAN) {
|
|
JcSDK.scanQrCb(funId, "activity result with code: " + resultCode, null);
|
|
}
|
|
funId = "";
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private Context getContext(){
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
protected void onStart() {
|
|
super.onStart();
|
|
if (mExecutor.isShutdown()) {
|
|
mExecutor = Executors.newSingleThreadExecutor();
|
|
}
|
|
}
|
|
|
|
// begin for unity
|
|
@Override
|
|
protected void onNewIntent(Intent intent) {
|
|
// To support deep linking, we need to make sure that the client can get access to
|
|
// the last sent intent. The clients access this through a JNI api that allows them
|
|
// to get the intent set on launch. To update that after launch we have to manually
|
|
// replace the intent with the one caught here.
|
|
setIntent(intent);
|
|
}
|
|
|
|
protected void onLoadNativeLibraries() {
|
|
try {
|
|
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
|
|
Bundle bundle = ai.metaData;
|
|
String libName = bundle.getString("android.app.lib_name");
|
|
System.loadLibrary(libName);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void showDialog(String pTitle, String pMessage) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void runOnGLThread(Runnable pRunnable) {
|
|
|
|
}
|
|
/** begin of easypermissions*/
|
|
@Override
|
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
|
|
// Forward results to EasyPermissions
|
|
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
|
}
|
|
|
|
@Override
|
|
public void onPermissionsGranted(int requestCode, List<String> list) {
|
|
// Some permissions have been granted
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onPermissionsDenied(int requestCode, List<String> list) {
|
|
// Some permissions have been denied
|
|
if ((requestCode == RC_CAMERA || requestCode == RC_READ_PHOTO) && null != funId && !"".equals(funId)) {
|
|
JcSDK.scanQrCb(funId, "User cancel", null);
|
|
funId = "";
|
|
} else if (requestCode == RC_LOAD_KEY) {
|
|
showQRScan(funId, "Scan QRCode for restore key.");
|
|
}
|
|
}
|
|
|
|
// end of easypermissions
|
|
|
|
// begin of qrcode
|
|
/**
|
|
* check if had permission for camera
|
|
*/
|
|
@AfterPermissionGranted(RC_CAMERA)
|
|
private void checkCameraPermissions(){
|
|
String[] perms = {Manifest.permission.CAMERA};
|
|
if (EasyPermissions.hasPermissions(this, perms)) {
|
|
startScan(title);
|
|
} else {
|
|
// Do not have permissions, request them now
|
|
EasyPermissions.requestPermissions(this, getString(R.string.permission_camera),
|
|
RC_CAMERA, perms);
|
|
}
|
|
}
|
|
@AfterPermissionGranted(RC_LOAD_KEY)
|
|
private void checkImagePermissions() {
|
|
String[] perms;
|
|
if (Build.VERSION.SDK_INT >= 33) {
|
|
perms = new String[]{"android.permission.READ_MEDIA_IMAGES"};
|
|
} else {
|
|
perms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
|
|
}
|
|
if (EasyPermissions.hasPermissions(this, perms)) {
|
|
Bitmap bitmap = FileUtils.loadImgData(this, oid);
|
|
if (bitmap != null) {
|
|
parsePhotoData(bitmap);
|
|
} else {
|
|
showQRScan(funId, "Scan QRCode for restore key.");
|
|
}
|
|
} else {
|
|
// Do not have permissions, request them now
|
|
EasyPermissions.requestPermissions(this, "Load Wallet restore key need read_media_images",
|
|
RC_LOAD_KEY, perms);
|
|
}
|
|
}
|
|
@AfterPermissionGranted(RC_SAVE_QR)
|
|
private void checkSavePermissions(){
|
|
String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
|
if (EasyPermissions.hasPermissions(this, perms)) {
|
|
if (qrCodeActivity != null) {
|
|
qrCodeActivity.saveAndClose();
|
|
}
|
|
} else {
|
|
// Do not have permissions, request them now
|
|
EasyPermissions.requestPermissions(MainActivity.app, "We need Write WRITE_EXTERNAL_STORAGE for backup Wallet Restore Key",
|
|
RC_SAVE_QR, perms);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* scan qrcode
|
|
*/
|
|
private void startScan(String title){
|
|
ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeCustomAnimation(this,R.anim.in,R.anim.out);
|
|
Intent intent = new Intent(this, CustomCaptureActivity.class);
|
|
// Intent intent = new Intent(this, CaptureActivity.class);
|
|
intent.putExtra(KEY_TITLE, title);
|
|
intent.putExtra(KEY_IS_CONTINUOUS, false);
|
|
runOnUiThread(() -> {
|
|
this.startActivityForResult(intent, REQUEST_CODE_SCAN, optionsCompat.toBundle());
|
|
});
|
|
|
|
}
|
|
|
|
private void asyncThread(Runnable runnable){
|
|
new Thread(runnable).start();
|
|
}
|
|
|
|
private void parsePhoto(Intent data){
|
|
try {
|
|
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),data.getData());
|
|
parsePhotoData(bitmap);
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
JcSDK.scanQrCb(funId, e.toString(), null);
|
|
funId = "";
|
|
}
|
|
}
|
|
private void parsePhotoData(Bitmap bitmap) {
|
|
asyncThread(() -> {
|
|
final String result = CodeUtils.parseQRCode(bitmap);
|
|
if (null == result || "".equals(result)) {
|
|
JcSDK.scanQrCb(funId, "no qrdeata", null);
|
|
} else {
|
|
LogUtils.d("result:" + result);
|
|
JcSDK.scanQrCb(funId, null, result);
|
|
}
|
|
funId = "";
|
|
});
|
|
}
|
|
|
|
public void showQRScan(String funId, String title) {
|
|
this.title = title;
|
|
this.funId = funId;
|
|
checkCameraPermissions();
|
|
}
|
|
|
|
public void loadRestoreKey(String fundId, String oid) {
|
|
this.funId = fundId;
|
|
this.oid = oid;
|
|
Log.i(TAG, "loadRestoreKey: " + oid);
|
|
checkImagePermissions();
|
|
}
|
|
|
|
/**
|
|
* start image scan
|
|
*/
|
|
public void startPhotoCode(String funId){
|
|
Intent pickIntent = new Intent(Intent.ACTION_PICK,
|
|
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
|
|
startActivityForResult(pickIntent, REQUEST_CODE_PHOTO);
|
|
}
|
|
|
|
// end of qrcode
|
|
public void signWithGoogle(String funId) {
|
|
this.funId = funId;
|
|
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
|
|
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
|
|
if (account != null) {
|
|
Log.w(TAG, "already login: " + account.getIdToken());
|
|
mGoogleSignInClient.silentSignIn()
|
|
.addOnCompleteListener(this, this::handleSignInResult);
|
|
} else {
|
|
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
|
|
startActivityForResult(signInIntent, RC_SIGN_IN);
|
|
}
|
|
} else {
|
|
Log.i(TAG, "no gms, use app auth");
|
|
AuthState state = mAuthStateManager.getCurrent();
|
|
if (state.isAuthorized() && state.getIdToken() != null) {
|
|
Log.w(TAG, "getNeedsTokenRefresh: " + state.getNeedsTokenRefresh());
|
|
if (state.getNeedsTokenRefresh()) {
|
|
Log.w(TAG, "need refresh accessToken");
|
|
TokenRequest tokenRequest = state.createTokenRefreshRequest();
|
|
performTokenRequest(
|
|
tokenRequest,
|
|
this::handleCodeExchangeResponse);
|
|
} else {
|
|
Log.w(TAG, "already login, accessToken not expired");
|
|
Log.w(TAG, "id token : " + state.getIdToken());
|
|
runOnUiThread(() -> successSdkCb(state.getIdToken()));
|
|
}
|
|
} else {
|
|
mExecutor.submit(this::doAuth);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void signOutGoogle(String funId) {
|
|
mGoogleSignInClient.signOut()
|
|
.addOnCompleteListener(this, task -> {
|
|
// ...
|
|
});
|
|
}
|
|
|
|
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
|
|
try {
|
|
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
|
|
Log.w(TAG, "signIn success: ");
|
|
Log.w(TAG, "gsa idToken: " + account.getIdToken());
|
|
runOnUiThread(() -> successSdkCb(account.getIdToken()));
|
|
// Signed in successfully, show authenticated UI.
|
|
} catch (ApiException e) {
|
|
// The ApiException status code indicates the detailed failure reason.
|
|
// Please refer to the GoogleSignInStatusCodes class reference for more information.
|
|
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
|
|
}
|
|
}
|
|
|
|
// begin of AppAuth
|
|
/**
|
|
* Initializes the authorization service configuration if necessary, either from the local
|
|
* static values or by retrieving an OpenID discovery document.
|
|
*/
|
|
@WorkerThread
|
|
private void initializeAppAuth() {
|
|
Log.i(TAG, "Initializing AppAuth");
|
|
recreateAuthorizationService();
|
|
|
|
if (mAuthStateManager.getCurrent().getAuthorizationServiceConfiguration() != null) {
|
|
// configuration is already created, skip to client initialization
|
|
Log.i(TAG, "auth config already established");
|
|
initializeClient();
|
|
return;
|
|
}
|
|
|
|
// if we are not using discovery, build the authorization service configuration directly
|
|
// from the static configuration values.
|
|
if (mConfiguration.getDiscoveryUri() == null) {
|
|
Log.i(TAG, "Creating auth config from res/raw/auth_config.json");
|
|
AuthorizationServiceConfiguration config = new AuthorizationServiceConfiguration(
|
|
mConfiguration.getAuthEndpointUri(),
|
|
mConfiguration.getTokenEndpointUri(),
|
|
mConfiguration.getRegistrationEndpointUri(),
|
|
mConfiguration.getEndSessionEndpoint());
|
|
|
|
mAuthStateManager.replace(new AuthState(config));
|
|
initializeClient();
|
|
return;
|
|
}
|
|
|
|
// WrongThread inference is incorrect for lambdas
|
|
// noinspection WrongThread
|
|
Log.i(TAG, "Retrieving OpenID discovery doc");
|
|
AuthorizationServiceConfiguration.fetchFromUrl(
|
|
mConfiguration.getDiscoveryUri(),
|
|
this::handleConfigurationRetrievalResult,
|
|
mConfiguration.getConnectionBuilder());
|
|
}
|
|
|
|
@MainThread
|
|
private void handleConfigurationRetrievalResult(
|
|
AuthorizationServiceConfiguration config,
|
|
AuthorizationException ex) {
|
|
if (config == null) {
|
|
Log.i(TAG, "Failed to retrieve discovery document", ex);
|
|
return;
|
|
}
|
|
|
|
Log.i(TAG, "Discovery document retrieved");
|
|
mAuthStateManager.replace(new AuthState(config));
|
|
mExecutor.submit(this::initializeClient);
|
|
}
|
|
|
|
private void recreateAuthorizationService() {
|
|
if (mAuthService != null) {
|
|
Log.i(TAG, "Discarding existing AuthService instance");
|
|
mAuthService.dispose();
|
|
}
|
|
mAuthService = createAuthorizationService();
|
|
mAuthRequest.set(null);
|
|
mAuthIntent.set(null);
|
|
}
|
|
|
|
private AuthorizationService createAuthorizationService() {
|
|
Log.i(TAG, "Creating authorization service");
|
|
AppAuthConfiguration.Builder builder = new AppAuthConfiguration.Builder();
|
|
builder.setBrowserMatcher(mBrowserMatcher);
|
|
builder.setConnectionBuilder(mConfiguration.getConnectionBuilder());
|
|
|
|
return new AuthorizationService(this, builder.build());
|
|
}
|
|
|
|
private void createAuthRequest(@Nullable String loginHint) {
|
|
Log.i(TAG, "Creating auth request for login hint: " + loginHint);
|
|
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
|
|
mAuthStateManager.getCurrent().getAuthorizationServiceConfiguration(),
|
|
mClientId.get(),
|
|
ResponseTypeValues.CODE,
|
|
mConfiguration.getRedirectUri())
|
|
.setScope(mConfiguration.getScope());
|
|
|
|
if (!TextUtils.isEmpty(loginHint)) {
|
|
authRequestBuilder.setLoginHint(loginHint);
|
|
}
|
|
|
|
mAuthRequest.set(authRequestBuilder.build());
|
|
}
|
|
|
|
private void warmUpBrowser() {
|
|
mAuthIntentLatch = new CountDownLatch(1);
|
|
mExecutor.execute(() -> {
|
|
Log.i(TAG, "Warming up browser instance for auth request");
|
|
CustomTabsIntent.Builder intentBuilder =
|
|
mAuthService.createCustomTabsIntentBuilder(mAuthRequest.get().toUri());
|
|
mAuthIntent.set(intentBuilder.build());
|
|
mAuthIntentLatch.countDown();
|
|
});
|
|
}
|
|
|
|
@MainThread
|
|
private void initializeAuthRequest() {
|
|
createAuthRequest("");
|
|
warmUpBrowser();
|
|
displayAuthOptions();
|
|
}
|
|
|
|
/**
|
|
* Initiates a dynamic registration request if a client ID is not provided by the static
|
|
* configuration.
|
|
*/
|
|
@WorkerThread
|
|
private void initializeClient() {
|
|
if (mConfiguration.getClientId() != null) {
|
|
Log.i(TAG, "Using static client ID: " + mConfiguration.getClientId());
|
|
// use a statically configured client ID
|
|
mClientId.set(mConfiguration.getClientId());
|
|
runOnUiThread(this::initializeAuthRequest);
|
|
return;
|
|
}
|
|
|
|
RegistrationResponse lastResponse =
|
|
mAuthStateManager.getCurrent().getLastRegistrationResponse();
|
|
if (lastResponse != null) {
|
|
Log.i(TAG, "Using dynamic client ID: " + lastResponse.clientId);
|
|
// already dynamically registered a client ID
|
|
mClientId.set(lastResponse.clientId);
|
|
runOnUiThread(this::initializeAuthRequest);
|
|
return;
|
|
}
|
|
|
|
// WrongThread inference is incorrect for lambdas
|
|
// noinspection WrongThread
|
|
Log.i(TAG, "Dynamically registering client");
|
|
|
|
RegistrationRequest registrationRequest = new RegistrationRequest.Builder(
|
|
mAuthStateManager.getCurrent().getAuthorizationServiceConfiguration(),
|
|
Collections.singletonList(mConfiguration.getRedirectUri()))
|
|
.setTokenEndpointAuthenticationMethod(ClientSecretBasic.NAME)
|
|
.build();
|
|
|
|
mAuthService.performRegistrationRequest(
|
|
registrationRequest,
|
|
this::handleRegistrationResponse);
|
|
}
|
|
|
|
private void handleRegistrationResponse(
|
|
RegistrationResponse response,
|
|
AuthorizationException ex) {
|
|
mAuthStateManager.updateAfterRegistration(response, ex);
|
|
if (response == null) {
|
|
Log.i(TAG, "Failed to dynamically register client", ex);
|
|
return;
|
|
}
|
|
|
|
Log.i(TAG, "Dynamically registered client: " + response.clientId);
|
|
mClientId.set(response.clientId);
|
|
initializeAuthRequest();
|
|
}
|
|
|
|
private void displayAuthOptions() {
|
|
AuthState state = mAuthStateManager.getCurrent();
|
|
AuthorizationServiceConfiguration config = state.getAuthorizationServiceConfiguration();
|
|
|
|
String authEndpointStr;
|
|
if (config.discoveryDoc != null) {
|
|
authEndpointStr = "Discovered auth endpoint: \n";
|
|
} else {
|
|
authEndpointStr = "Static auth endpoint: \n";
|
|
}
|
|
authEndpointStr += config.authorizationEndpoint;
|
|
Log.i(TAG, authEndpointStr);
|
|
|
|
String clientIdStr;
|
|
if (state.getLastRegistrationResponse() != null) {
|
|
clientIdStr = "Dynamic client ID: \n";
|
|
} else {
|
|
clientIdStr = "Static client ID: \n";
|
|
}
|
|
clientIdStr += mClientId;
|
|
Log.i(TAG, clientIdStr);
|
|
}
|
|
|
|
/**
|
|
* Performs the authorization request, using the browser selected in the spinner,
|
|
* and a user-provided `login_hint` if available.
|
|
*/
|
|
@WorkerThread
|
|
private void doAuth() {
|
|
try {
|
|
mAuthIntentLatch.await();
|
|
} catch (InterruptedException ex) {
|
|
Log.w(TAG, "Interrupted while waiting for auth intent");
|
|
}
|
|
|
|
Intent intent = mAuthService.getAuthorizationRequestIntent(
|
|
mAuthRequest.get(),
|
|
mAuthIntent.get());
|
|
startActivityForResult(intent, RC_AUTH);
|
|
}
|
|
|
|
@MainThread
|
|
private void exchangeAuthorizationCode(AuthorizationResponse authorizationResponse) {
|
|
Log.d(TAG, "Exchanging authorization code");
|
|
performTokenRequest(
|
|
authorizationResponse.createTokenExchangeRequest(),
|
|
this::handleCodeExchangeResponse);
|
|
}
|
|
|
|
@MainThread
|
|
private void performTokenRequest(
|
|
TokenRequest request,
|
|
AuthorizationService.TokenResponseCallback callback) {
|
|
ClientAuthentication clientAuthentication;
|
|
try {
|
|
clientAuthentication = mAuthStateManager.getCurrent().getClientAuthentication();
|
|
} catch (ClientAuthentication.UnsupportedAuthenticationMethod ex) {
|
|
Log.d(TAG, "Token request cannot be made, client authentication for the token "
|
|
+ "endpoint could not be constructed (%s)", ex);
|
|
return;
|
|
}
|
|
|
|
mAuthService.performTokenRequest(
|
|
request,
|
|
clientAuthentication,
|
|
callback);
|
|
}
|
|
|
|
@WorkerThread
|
|
private void handleCodeExchangeResponse(
|
|
@Nullable TokenResponse tokenResponse,
|
|
@Nullable AuthorizationException authException) {
|
|
|
|
mAuthStateManager.updateAfterTokenResponse(tokenResponse, authException);
|
|
if (!mAuthStateManager.getCurrent().isAuthorized()) {
|
|
final String message = "Authorization Code exchange failed"
|
|
+ ((authException != null) ? authException.error : "");
|
|
|
|
// WrongThread inference is incorrect for lambdas
|
|
//noinspection WrongThread
|
|
Log.d(TAG, message);
|
|
} else {
|
|
AuthState state = mAuthStateManager.getCurrent();
|
|
Log.d(TAG, "login success, auth state: " + state.isAuthorized());
|
|
Log.d(TAG, "app auth idToken: " + state.getIdToken());
|
|
mAuthStateManager.replace(state);
|
|
runOnUiThread(() -> successSdkCb(state.getIdToken()));
|
|
}
|
|
}
|
|
@MainThread
|
|
private void successSdkCb(String idToken) {
|
|
JcSDK.oauthCb(this.funId, null, idToken);
|
|
}
|
|
|
|
@MainThread
|
|
private void errorSdkCb(String errMsg) {
|
|
JcSDK.oauthCb(this.funId, errMsg, null);
|
|
}
|
|
|
|
// sign with tiktok
|
|
public void signWithTiktok(String funId) {
|
|
this.funId = funId;
|
|
Log.i(TAG, "login with tiktok: " + funId);
|
|
// STEP 1: Create an instance of TiktokOpenApi
|
|
TikTokOpenApi tiktokOpenApi= TikTokOpenApiFactory.create(this);
|
|
|
|
// STEP 2: Create an instance of Authorization.Request and set parameters
|
|
Authorization.Request request = new Authorization.Request();
|
|
request.scope = "user.info.basic,video.list";
|
|
request.state = funId;
|
|
tiktokOpenApi.authorize(request);
|
|
}
|
|
|
|
|
|
public void showQRCode(String funid, String str, String title, String oid) {
|
|
runOnUiThread(() -> {
|
|
if (qrCodeActivity == null) {
|
|
qrCodeActivity = new QRCodeActivity(getContext());
|
|
}
|
|
qrCodeActivity.showQRCode(str, title, oid);
|
|
qrCodeActivity.show();
|
|
});
|
|
}
|
|
|
|
public void showToast(String text) {
|
|
runOnUiThread(() -> {
|
|
if(toast == null){
|
|
toast = Toast.makeText(this,text,Toast.LENGTH_SHORT);
|
|
}else{
|
|
toast.setDuration(Toast.LENGTH_SHORT);
|
|
toast.setText(text);
|
|
}
|
|
toast.show();
|
|
});
|
|
}
|
|
|
|
// begin of facebook login
|
|
private void initFacebookSDK() {
|
|
mCallbackManager = CallbackManager.Factory.create();
|
|
LoginManager.getInstance().registerCallback(mCallbackManager,
|
|
new FacebookCallback<LoginResult>() {
|
|
@Override
|
|
public void onSuccess(LoginResult loginResult) {
|
|
AccessToken accessToken = AccessToken.getCurrentAccessToken();
|
|
Log.d(TAG, "Login Success:: accessToken: " + accessToken.getToken());
|
|
if (!verifyFbAccessToken(accessToken)) {
|
|
runOnUiThread(() -> errorSdkCb("access token expired"));
|
|
}
|
|
}
|
|
@Override
|
|
public void onCancel() {
|
|
Log.d(TAG, "Login cancel");
|
|
runOnUiThread(() -> errorSdkCb("user login cancel"));
|
|
}
|
|
|
|
@Override
|
|
public void onError(FacebookException exception) {
|
|
Log.i(TAG, "Login error: " + exception.getMessage());
|
|
runOnUiThread(() -> errorSdkCb(exception.getMessage()));
|
|
}
|
|
});
|
|
}
|
|
|
|
public void signWithFacebook(String funId) {
|
|
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) {
|
|
ShareLinkContent linkContent = new ShareLinkContent.Builder()
|
|
.setContentUrl(Uri.parse("https://www.baidu.com"))
|
|
.setQuote(content)
|
|
.build();
|
|
ShareDialog.show(this, linkContent);
|
|
}
|
|
|
|
private boolean verifyFbAccessToken(AccessToken accessToken) {
|
|
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();
|
|
if (isLoggedIn) {
|
|
runOnUiThread(() -> successSdkCb(accessToken.getToken()));
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
// end of facebook login
|
|
|
|
public void signWithTwitter(String funId) {
|
|
Log.i(TAG, "login with twitter: " + funId);
|
|
this.funId = funId;
|
|
}
|
|
} |