diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 7e42cec..e1eea1d 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/Classes/JcWallet.cpp b/Classes/JcWallet.cpp index 0622191..81a7b57 100644 --- a/Classes/JcWallet.cpp +++ b/Classes/JcWallet.cpp @@ -17,7 +17,8 @@ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #ifndef COM_JC_JCFW_CLASS_NAME -#define COM_JC_JCFW_CLASS_NAME com_jc_jcfw_JcSDK +// Java_com_jc_jcfw_JcSDK_00024Companion_runJS +#define COM_JC_JCFW_CLASS_NAME com_jc_jcfw_JcSDK_00024Companion #endif #define JNI_JCFW(FUNC) JNI_METHOD1(COM_JC_JCFW_CLASS_NAME, FUNC) @@ -259,7 +260,7 @@ extern "C" return result == 0 ? 1 : 0; } #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) - JNIEXPORT jint JNICALL JNI_JCFW(runJS)(JNIEnv *env, jclass clazz, jstring j_fun_id, jstring j_method_name, jobjectArray j_params) + JNIEXPORT jint JNICALL JNI_JCFW(runJS)(JNIEnv *env, jobject clazz, jstring j_fun_id, jstring j_method_name, jobjectArray j_params) { if (!_isStarted) { return 0; @@ -285,7 +286,7 @@ extern "C" return result == 0 ? 1 : 0; } - JNIEXPORT jstring JNICALL JNI_JCFW(decryptPass)(JNIEnv *env, jclass clazz, jstring jaccount, jstring jpass) + JNIEXPORT jstring JNICALL JNI_JCFW(decryptPass)(JNIEnv *env, jobject clazz, jstring jaccount, jstring jpass) { std::string pass_encrypted = JniHelper::jstring2string(jpass); std::string account = JniHelper::jstring2string(jaccount); @@ -293,7 +294,7 @@ extern "C" std::string passDecrypt = decrypt_aes(pass_encrypted, keyStr); return env->NewStringUTF(passDecrypt.c_str()); } - JNIEXPORT void JNICALL JNI_JCFW(tick)(JNIEnv *env, jclass clazz, jfloat dt) + JNIEXPORT void JNICALL JNI_JCFW(tick)(JNIEnv *env, jobject clazz, jfloat dt) { tick2(dt); } @@ -352,4 +353,4 @@ bool jsb_register_walletevent_modules(se::Object *global) getOrCreatePlainObject_r("jsb", global, &__jsbObj); __jsbObj->defineFunction("jcCallback", _SE(jsb_wallet_callback)); return true; -} +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index d316333..cd969d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,6 +7,7 @@ plugins { id 'com.google.gms.google-services' // Add the Crashlytics Gradle plugin id 'com.google.firebase.crashlytics' + id 'org.jetbrains.kotlin.android' } android { compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger() diff --git a/app/src/com/ctf/games/release/MainActivity.kt b/app/src/com/ctf/games/release/MainActivity.kt index ce0fc0e..6d7a567 100644 --- a/app/src/com/ctf/games/release/MainActivity.kt +++ b/app/src/com/ctf/games/release/MainActivity.kt @@ -100,14 +100,14 @@ class MainActivity : UnityPlayerActivity(), Cocos2dxHelperListener { initFacebookSDK() // end of facebook login tiktokOpenApi = TikTokOpenApiFactory.create(this) - val payClient = PayClient.getInstance() - payClient.init(this) + val payClient = PayClient.instance + payClient?.init(this) mWalletUtil = WalletUtil(this) } override fun onResume() { super.onResume() - val paramArr = arrayOf() + val paramArr = arrayOfNulls(0) JcSDK.callNativeJS("", "onGameResume", paramArr) } @@ -483,19 +483,19 @@ class MainActivity : UnityPlayerActivity(), Cocos2dxHelperListener { Log.d(TAG, "need refresh accessToken") mAppAuthSvr!!.refreshToken(funID) { mWalletUtil!!.downloadCfgWithApi( - state.accessToken + state.accessToken!! ) { mWalletUtil!!.passLocal } } } else { Log.d(TAG, "access token no need refresh") - mWalletUtil!!.downloadCfgWithApi(state.accessToken) { mWalletUtil!!.passLocal } + mWalletUtil!!.downloadCfgWithApi(state.accessToken!!) { mWalletUtil!!.passLocal } } } else { Log.w(TAG, "not login") mExecutor!!.submit { mAppAuthSvr!!.doAuth(funID) { mWalletUtil!!.downloadCfgWithApi( - state.accessToken + state.accessToken!! ) { mWalletUtil!!.passLocal } } } diff --git a/app/src/com/ctf/games/release/wallet/WalletUtil.kt b/app/src/com/ctf/games/release/wallet/WalletUtil.kt index 562165b..bb1bcc9 100644 --- a/app/src/com/ctf/games/release/wallet/WalletUtil.kt +++ b/app/src/com/ctf/games/release/wallet/WalletUtil.kt @@ -109,15 +109,15 @@ class WalletUtil(private val mContext: Context) { fileId = DriveUtils.uploadAppFile(service, file, "application/json") } Log.i(TAG, "File ID: $fileId") - func.accept(NativeResult(funID, null, fileId)) + func.accept(NativeResult(funID!!, null, fileId)) successCB(fileId) } catch (e: GoogleJsonResponseException) { Log.i(TAG, "Unable to create file: " + e.details) - func.accept(NativeResult(funID, e.message, null)) + func.accept(NativeResult(funID!!, e.message, null)) errorCB("Unable to create file: " + e.message) } catch (e: IOException) { Log.i(TAG, e.message!!) - func.accept(NativeResult(funID, e.message, null)) + func.accept(NativeResult(funID!!, e.message, null)) errorCB("Unable to create file: " + e.message) } } @@ -155,7 +155,7 @@ class WalletUtil(private val mContext: Context) { } } - fun downloadCfgWithApi(accessToken: String?, func: Consumer) { + fun downloadCfgWithApi(accessToken: String, func: Consumer) { val api = DriverApiUtils(accessToken) val fileName = generateFileName(account) val fileLocal = getWalletCfgFile(account) @@ -186,7 +186,7 @@ class WalletUtil(private val mContext: Context) { } fun uploadCfgWithApi(accessToken: String?, func: Consumer) { - val api = DriverApiUtils(accessToken) + val api = DriverApiUtils(accessToken!!) val fileLocal = getWalletCfgFile(account) try { val fileName = generateFileName(account) @@ -197,13 +197,13 @@ class WalletUtil(private val mContext: Context) { fileId = repData.getString("id") } Log.i(TAG, "success upload file with api, ID: $fileId") - func.accept(NativeResult(funID, null, fileId)) + func.accept(NativeResult(funID!!, null, fileId)) successCB(fileId) } catch (e: IOException) { - func.accept(NativeResult(funID, e.message, null)) + func.accept(NativeResult(funID!!, e.message, null)) errorCB("error upload file with api: " + e.message) } catch (e: JSONException) { - func.accept(NativeResult(funID, e.message, null)) + func.accept(NativeResult(funID!!, e.message, null)) errorCB("error upload file with api: " + e.message) } } diff --git a/app/src/com/ctf/games/release/webpage/WalletInterface.kt b/app/src/com/ctf/games/release/webpage/WalletInterface.kt index 68bdeb8..e41a72e 100644 --- a/app/src/com/ctf/games/release/webpage/WalletInterface.kt +++ b/app/src/com/ctf/games/release/webpage/WalletInterface.kt @@ -10,6 +10,6 @@ class WalletInterface // sign @JavascriptInterface fun pageCall(dataStr: String?) { - EventBus.getDefault().post(WebPageEvent(dataStr)) + EventBus.getDefault().post(WebPageEvent(dataStr!!)) } } \ No newline at end of file diff --git a/app/src/com/jc/jcfw/JcSDK.java b/app/src/com/jc/jcfw/JcSDK.java deleted file mode 100644 index a8c41ae..0000000 --- a/app/src/com/jc/jcfw/JcSDK.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.jc.jcfw; - -import static com.ctf.games.release.Constants.FUNID_PREFIX; - -import android.annotation.SuppressLint; -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.net.Uri; -import android.util.Log; - -import com.ctf.games.release.MainActivity; -import com.ctf.games.release.MainApplication; -import com.ctf.games.release.ui.UIManager; -import com.ctf.games.release.webpage.events.CallJSEvent; -import com.ctf.games.release.webpage.events.ProxyCBEvent; -import com.google.common.base.Strings; -import com.jc.jcfw.google.PayClient; -import com.jc.jcfw.util.ThreadUtils; -import com.jc.jcfw.util.UIUtils; - -import org.cocos2dx.lib.CocosJSHelper; -import org.greenrobot.eventbus.EventBus; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -public class JcSDK { - private static final String TAG = JcSDK.class.getSimpleName(); - private static UnityCallback commonCB; - - @SuppressLint("StaticFieldLeak") - private static PayClient payClient; - - 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 native void tick(float dt); - - public static void initCommonCB(UnityCallback callBack) { - Log.i(TAG, "call init common callback from unity"); - commonCB = callBack; - } - - /** - * @Deprecated - * 不使用该方法, 直接由unity调用cpp方法 - * @param password - */ - public static void initWallet(String password) { - Log.i(TAG, "call init wallet from unity with password: " + password); - CocosJSHelper.initWallet(password); - commonCB.nativeCallback("", "wallet init success", 0); - } - - /** - * 回调至c# - */ - public static void csCallback(String funId, String msg) { - if (!Objects.equals(funId, "") && funId.indexOf("js_") == 0) { - commonCB.nativeCallback(funId, msg, 1); - } else { - commonCB.nativeCallback(funId, msg, 0); - } - } - - /** - * check if metamask installed and jump to metamask - * - * @param url - * sample: - * "https://metamask.app.link/wc?uri="+ExampleApplication.config.toWCUri(); - */ - - public static void toWallet(String url) { - Intent intent = new Intent(Intent.ACTION_VIEW); - Log.i(TAG, url); - try { - intent.setData(Uri.parse(url)); - MainActivity.app.startActivity(intent); - } catch (ActivityNotFoundException e) { - Intent i = new Intent(Intent.ACTION_VIEW); - String downloadUrl = "https://metamask.io/download/"; - if (url.startsWith("imtokenv2")) { - downloadUrl = "https://token.im/download"; - } else if (url.startsWith("okx://")) { - downloadUrl = "https://www.okx.com/download"; - } - i.setData(Uri.parse(downloadUrl)); - MainActivity.app.startActivity(i); - } - } - - public static void showQRCode(String funid, String content) { - UIUtils.showQRCode(MainActivity.app, content, ""); - } - - public static void showWebPage(String funid, String url) { - MainActivity.app.showPage(funid, url); - } - - public static void scanQRCode(String funid, String title) { - // MainActivity.app.showQRScan(funid, title); - UIManager.getSingleton().showQRScan(funid, title); - } - - public static void signWithTiktok(String funid) { - MainActivity.app.signWithTiktok(funid); - } - - public static void signWithFacebook(String funid) { - MainActivity.app.signWithFacebook(funid); - } - - public static void shareWithFacebook(String content) { - MainActivity.app.shareWithFacebook(content); - } - - public static void signWithTwitter(String funid) { - MainActivity.app.signWithTwitter(funid); - } - - public static void signWithGoogle(String funid) { - MainActivity.app.signWithGoogle(funid); - } - - public static void signWithApple(String funid) { - MainActivity.app.signWithApple(funid); - } - - public static void signOutGoogle(String funid) { - MainActivity.app.signOutGoogle(funid); - } - - public static void logEvent(String content) { - MainActivity.app.logEvent(content); - } - - public static void queryProducts(String funid, String skuListStr) { - Log.i(TAG, "queryProducts with: " + skuListStr); - if (payClient == null) { - payClient = PayClient.getInstance(); - } - List skuList = new ArrayList<>(); - if (skuListStr.contains(",")) { - String[] skuArr = skuListStr.split(","); - skuList.addAll(Arrays.asList(skuArr)); - } else { - skuList.add(skuListStr); - } - payClient.queryProductList(funid, skuList); - } - - public static void buyProduct(String funid, String productId, String orderId) { - Log.i(TAG, "buyProduct with: " + productId); - if (payClient == null) { - payClient = PayClient.getInstance(); - } - payClient.buyOne(funid, productId, orderId); - } - - public static void queryPurchase(String funid) { - Log.i(TAG, "queryPurchase"); - if (payClient == null) { - payClient = PayClient.getInstance(); - } - payClient.queryPurchase(funid); - } - - public static void passStorageState(String funid, String account) { - Log.i(TAG, "passStorageState with: " + account); - MainActivity.app.passStorageState(funid, account); - } - - public static void storagePass(String funid, String account, String password) { - MainActivity.app.storagePass(funid, account, password); - } - - public static void authGetStoragePass(String funid, String account) { - MainActivity.app.authGetStoragePass(funid, account); - } - - public static void storageGameData(String data) { - MainApplication.application.setGameData(data); - } - - public static void getClientId(String funid) { - Log.i(TAG, "getClientId "); - MainActivity.app.getClientId(funid); - } - - public static void onProxyCB(String funId, String data) { - EventBus.getDefault().post(new ProxyCBEvent(funId, data)); - } - - public static void nativeCb(String funId, String error, String dataStr) { - JSONObject result = new JSONObject(); - try { - 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()); - } - if (funId == null || funId.isEmpty()) { - funId = MainActivity.app.getFunId(); - } - Log.i(TAG, String.format("%s native cb, error: %s, data: %s", funId, error, dataStr)); - if (funId.startsWith(FUNID_PREFIX)) { - EventBus.getDefault().post(new CallJSEvent(funId, result.toString())); - } else { - String finalFunId = funId; - ThreadUtils.runInMain(() -> JcSDK.runJS(finalFunId, "jniCallback", new String[]{result.toString()})); - } - } - - public static void callNativeJS(String funId, String methodName, String[] params) { - ThreadUtils.runInMain(() -> JcSDK.runJS(funId, methodName, params)); - } - - public static void nativeCb(NativeResult result) { - nativeCb(result.getFunid(), result.getError(), result.getDataStr()); - } -} diff --git a/app/src/com/jc/jcfw/JcSDK.kt b/app/src/com/jc/jcfw/JcSDK.kt new file mode 100644 index 0000000..7c363df --- /dev/null +++ b/app/src/com/jc/jcfw/JcSDK.kt @@ -0,0 +1,237 @@ +package com.jc.jcfw + +import android.annotation.SuppressLint +import android.content.ActivityNotFoundException +import android.content.Intent +import android.net.Uri +import android.util.Log +import com.ctf.games.release.MainActivity +import com.ctf.games.release.MainApplication +import com.ctf.games.release.ui.UIManager.Companion.singleton +import com.ctf.games.release.webpage.events.CallJSEvent +import com.ctf.games.release.webpage.events.ProxyCBEvent +import com.google.common.base.Strings +import com.jc.jcfw.google.PayClient +import com.jc.jcfw.util.ThreadUtils +import com.jc.jcfw.util.UIUtils +import org.cocos2dx.lib.CocosJSHelper +import org.greenrobot.eventbus.EventBus +import org.json.JSONException +import org.json.JSONObject +import java.util.Arrays + +const val FUNID_PREFIX = "webpage_" +class JcSDK { + companion object { + external fun runJS(funId: String?, methodName: String, params: Array): Int + external fun decryptPass(account: String?, pass: String?): String? + external fun tick(dt: Float) + + private val TAG = JcSDK::class.java.simpleName + private var commonCB: UnityCallback? = null + @SuppressLint("StaticFieldLeak") + private var payClient: PayClient? = null + + @JvmStatic + fun initCommonCB(callBack: UnityCallback?) { + Log.i(TAG, "call init common callback from unity") + commonCB = callBack + } + + /** + * @Deprecated + * 不使用该方法, 直接由unity调用cpp方法 + * @param password + */ + @JvmStatic + fun initWallet(password: String) { + Log.i(TAG, "call init wallet from unity with password: $password") + CocosJSHelper.initWallet(password) + commonCB!!.nativeCallback("", "wallet init success", 0) + } + + /** + * 回调至c# + */ + @JvmStatic + fun csCallback(funId: String, msg: String?) { + if (funId != "" && funId.indexOf("js_") == 0) { + commonCB!!.nativeCallback(funId, msg, 1) + } else { + commonCB!!.nativeCallback(funId, msg, 0) + } + } + + /** + * check if metamask installed and jump to metamask + * + * @param url + * sample: + * "https://metamask.app.link/wc?uri="+ExampleApplication.config.toWCUri(); + */ + @JvmStatic + fun toWallet(url: String) { + val intent = Intent(Intent.ACTION_VIEW) + Log.i(TAG, url) + try { + intent.data = Uri.parse(url) + MainActivity.app!!.startActivity(intent) + } catch (e: ActivityNotFoundException) { + val i = Intent(Intent.ACTION_VIEW) + var downloadUrl = "https://metamask.io/download/" + if (url.startsWith("imtokenv2")) { + downloadUrl = "https://token.im/download" + } else if (url.startsWith("okx://")) { + downloadUrl = "https://www.okx.com/download" + } + i.data = Uri.parse(downloadUrl) + MainActivity.app!!.startActivity(i) + } + } + + @JvmStatic + fun showQRCode(funid: String?, content: String?) { + UIUtils.showQRCode(MainActivity.app, content, "") + } + + @JvmStatic + fun showWebPage(funid: String?, url: String?) { + MainActivity.app!!.showPage(funid, url) + } + + @JvmStatic + fun scanQRCode(funid: String?, title: String?) { + // MainActivity.app.showQRScan(funid, title); + singleton!!.showQRScan(funid, title) + } + + @JvmStatic + fun signWithTiktok(funid: String?) { + MainActivity.app!!.signWithTiktok(funid!!) + } + + @JvmStatic + fun signWithFacebook(funid: String?) { + MainActivity.app!!.signWithFacebook(funid!!) + } + + @JvmStatic + fun shareWithFacebook(content: String?) { + MainActivity.app!!.shareWithFacebook(content) + } + + @JvmStatic + fun signWithTwitter(funid: String?) { + MainActivity.app!!.signWithTwitter(funid!!) + } + + @JvmStatic + fun signWithGoogle(funid: String?) { + MainActivity.app!!.signWithGoogle(funid) + } + @JvmStatic + fun signWithApple(funid: String?) { + MainActivity.app!!.signWithApple(funid!!) + } + @JvmStatic + fun signOutGoogle(funid: String?) { + MainActivity.app!!.signOutGoogle(funid) + } + @JvmStatic + fun logEvent(content: String?) { + MainActivity.app!!.logEvent(content) + } + @JvmStatic + fun queryProducts(funid: String?, skuListStr: String) { + Log.i(TAG, "queryProducts with: $skuListStr") + if (payClient == null) { + payClient = PayClient.instance + } + val skuList: MutableList = ArrayList() + if (skuListStr.contains(",")) { + val skuArr = skuListStr.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + skuList.addAll(Arrays.asList(*skuArr)) + } else { + skuList.add(skuListStr) + } + payClient!!.queryProductList(funid, skuList) + } + @JvmStatic + fun buyProduct(funid: String?, productId: String, orderId: String?) { + Log.i(TAG, "buyProduct with: $productId") + if (payClient == null) { + payClient = PayClient.instance + } + payClient!!.buyOne(funid, productId, orderId) + } + @JvmStatic + fun queryPurchase(funid: String?) { + Log.i(TAG, "queryPurchase") + if (payClient == null) { + payClient = PayClient.instance + } + payClient!!.queryPurchase(funid) + } + @JvmStatic + fun passStorageState(funid: String?, account: String) { + Log.i(TAG, "passStorageState with: $account") + MainActivity.app!!.passStorageState(funid, account) + } + @JvmStatic + fun storagePass(funid: String?, account: String?, password: String?) { + MainActivity.app!!.storagePass(funid, account, password) + } + @JvmStatic + fun authGetStoragePass(funid: String?, account: String?) { + MainActivity.app!!.authGetStoragePass(funid, account!!) + } + @JvmStatic + fun storageGameData(data: String?) { + MainApplication.application!!.gameData = data + } + @JvmStatic + fun getClientId(funid: String?) { + Log.i(TAG, "getClientId ") + MainActivity.app!!.getClientId(funid) + } + @JvmStatic + fun onProxyCB(funId: String?, data: String?) { + EventBus.getDefault().post(ProxyCBEvent(funId!!, data!!)) + } + + fun nativeCb(funId: String?, error: String?, dataStr: String?) { + var funId = funId + val result = JSONObject() + try { + if (Strings.isNullOrEmpty(error)) { + result.put("errcode", 0) + result.put("data", dataStr) + } else { + result.put("errcode", 1) + result.put("errmessage", error) + } + } catch (e: JSONException) { + Log.e(TAG, "JSONException: " + e.message) + } + if (funId == null || funId.isEmpty()) { + funId = MainActivity.app!!.funId + } + Log.i(TAG, String.format("%s native cb, error: %s, data: %s", funId, error, dataStr)) + if (funId != null && funId.startsWith(FUNID_PREFIX)) { + EventBus.getDefault().post(CallJSEvent(funId, result.toString())) + } else { + val finalFunId = funId + ThreadUtils.runInMain { runJS(finalFunId, "jniCallback", arrayOf(result.toString())) } + } + } + + fun callNativeJS(funId: String?, methodName: String, params: Array) { + ThreadUtils.runInMain { runJS(funId, methodName, params) } + } + + fun nativeCb(result: NativeResult) { + nativeCb(result.funid, result.error, result.dataStr) + } + } + +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/NativeResult.java b/app/src/com/jc/jcfw/NativeResult.java deleted file mode 100644 index b021c54..0000000 --- a/app/src/com/jc/jcfw/NativeResult.java +++ /dev/null @@ -1,37 +0,0 @@ -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; - } -} diff --git a/app/src/com/jc/jcfw/NativeResult.kt b/app/src/com/jc/jcfw/NativeResult.kt new file mode 100644 index 0000000..97635be --- /dev/null +++ b/app/src/com/jc/jcfw/NativeResult.kt @@ -0,0 +1,3 @@ +package com.jc.jcfw + +class NativeResult(var funid: String, var error: String?, var dataStr: String?) \ No newline at end of file diff --git a/app/src/com/jc/jcfw/UnityCallback.java b/app/src/com/jc/jcfw/UnityCallback.java deleted file mode 100644 index 6c53b7f..0000000 --- a/app/src/com/jc/jcfw/UnityCallback.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.jc.jcfw; - -public interface UnityCallback { - public void nativeCallback(String funId, String str, int type); -} diff --git a/app/src/com/jc/jcfw/UnityCallback.kt b/app/src/com/jc/jcfw/UnityCallback.kt new file mode 100644 index 0000000..cab947c --- /dev/null +++ b/app/src/com/jc/jcfw/UnityCallback.kt @@ -0,0 +1,5 @@ +package com.jc.jcfw + +interface UnityCallback { + fun nativeCallback(funId: String?, str: String?, type: Int) +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/google/PayClient.java b/app/src/com/jc/jcfw/google/PayClient.java deleted file mode 100644 index f53ac3f..0000000 --- a/app/src/com/jc/jcfw/google/PayClient.java +++ /dev/null @@ -1,251 +0,0 @@ -package com.jc.jcfw.google; - -import android.app.Activity; -import android.content.Context; -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.android.billingclient.api.BillingClient; -import com.android.billingclient.api.BillingClientStateListener; -import com.android.billingclient.api.BillingFlowParams; -import com.android.billingclient.api.BillingResult; -import com.android.billingclient.api.ProductDetails; -import com.android.billingclient.api.Purchase; -import com.android.billingclient.api.PurchasesUpdatedListener; -import com.android.billingclient.api.QueryProductDetailsParams; -import com.android.billingclient.api.QueryPurchasesParams; -import com.ctf.games.release.MainActivity; -import com.jc.jcfw.JcSDK; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class PayClient extends Activity implements PurchasesUpdatedListener { - private static final String TAG = "GooglePayClient"; - private static volatile PayClient mInstance = null; - private static BillingClient billingClient; - private static ConcurrentHashMap skuDetailsMap; - private Context mContext = null; - private String mFunId; - - public static PayClient getInstance() { - if (null == mInstance) { - synchronized (PayClient.class) { - if (null == mInstance) { - mInstance = new PayClient(); - } - } - } - return mInstance; - } - - public void init(Context context) { - this.mContext = context; - skuDetailsMap = new ConcurrentHashMap<>(); - billingClient = BillingClient.newBuilder(context).enablePendingPurchases().setListener(this).build(); - connectToPlay(); - } - - private void connectToPlay() { - billingClient.startConnection(new BillingClientStateListener() { - @Override - public void onBillingSetupFinished(@NonNull BillingResult billingResult) { - Log.i(TAG, "onBillingSetupFinished, response code: " + billingResult.getResponseCode()); - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - // The BillingClient is ready. You can query purchases here. - Log.i(TAG, "BillingClient is ready"); - } else { - Log.i(TAG, "error init BillingClient with error:: " +billingResult.getResponseCode()); - } - } - - @Override - public void onBillingServiceDisconnected() { - // Try to restart the connection on the next request to - // Google Play by calling the startConnection() method. - connectToPlay(); - } - }); - } - - JSONArray handlePurchase(JSONArray dataArr, Purchase purchase) throws JSONException { - if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED -// || purchase.getPurchaseState() == Purchase.PurchaseState.PENDING - ) { - // Acknowledge purchase and grant the item to the user - // Grant entitlement to the user. - Log.i(TAG, "handlePurchase:" + purchase.getOriginalJson()); - Log.i(TAG, "purchase sign:" + purchase.getSignature()); - if (!purchase.isAcknowledged() && purchase.getProducts().size() > 0) { - // consumables 消耗型 - JSONObject data = new JSONObject(); - data.put("id", purchase.getProducts().get(0)); - data.put("token", purchase.getPurchaseToken()); - dataArr.put(data); - } - } - return dataArr; - } - - @Override - public void onPurchasesUpdated(BillingResult billingResult, List purchases) { - Log.i(TAG, "onPurchasesUpdated with status: " + billingResult.getResponseCode()); - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK - && purchases != null) { - final JSONArray dataArr = new JSONArray(); - boolean hasErr = false; - for (Purchase purchase : purchases) { - try { - handlePurchase(dataArr, purchase); - } catch (JSONException e) { - hasErr = true; - break; - } - } - if (hasErr) { - purchaseUpdateCb(null,"error parse purchase data", null); - } else { - purchaseUpdateCb(null,null, dataArr.toString()); - } - } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) { - purchaseUpdateCb(null,"user cancel buy", null); - } else { - String errmsg = billingResult.getDebugMessage(); - if (errmsg.isEmpty()) { - errmsg = "other error"; - } - purchaseUpdateCb(null, errmsg, null); - } - } - private void purchaseUpdateCb(String funId, String error, String dataStr) { - if (funId == null || funId.isEmpty()) { - if (mFunId != null && !mFunId.isEmpty()) { - final String _funId = mFunId; - runOnUiThread(() -> JcSDK.nativeCb(_funId, error, dataStr)); - mFunId = null; - } - } else { - runOnUiThread(() -> JcSDK.nativeCb(funId, error, dataStr)); - } - - } - private boolean parseProductDetails(JSONArray dataArr, ProductDetails skuDetails) { - JSONObject data = new JSONObject(); - try { - data.put("name", skuDetails.getTitle()); - data.put("description", skuDetails.getDescription()); - data.put("id", skuDetails.getProductId()); - data.put("type", skuDetails.getProductType()); - if (skuDetails.getProductType().equals(BillingClient.ProductType.INAPP)) { - data.put("currencyCode", - skuDetails.getOneTimePurchaseOfferDetails().getPriceCurrencyCode()); - data.put("priceValue", skuDetails.getOneTimePurchaseOfferDetails().getPriceAmountMicros()); - data.put("priceShow", skuDetails.getOneTimePurchaseOfferDetails().getFormattedPrice()); - } - dataArr.put(data); - return true; - } catch (JSONException e) { - e.printStackTrace(); - return false; - } - } - public void queryProductList(String funId, List productIds) { - List productList = new ArrayList<>(); - for (String productId : productIds) { - productList.add( - QueryProductDetailsParams.Product.newBuilder() - .setProductId(productId) - .setProductType(BillingClient.ProductType.INAPP) - .build()); - } - QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder() - .setProductList(productList) - .build(); - billingClient.queryProductDetailsAsync( - params, - (billingResult, productDetailsList) -> { - // Process the result - Map pMap = new HashMap<>(); - for (ProductDetails details : productDetailsList) { - skuDetailsMap.put(details.getProductId(), details); - pMap.put(details.getProductId(), details); - } - final JSONArray dataArr = new JSONArray(); - boolean hasErr = false; - for (Map.Entry entry : pMap.entrySet()) { - ProductDetails skuDetails = entry.getValue(); - if (!parseProductDetails(dataArr, skuDetails)) { - hasErr = true; - break; - } - } - if (hasErr) { - purchaseUpdateCb(funId, "parse product detail json error", null); - } else { - purchaseUpdateCb(funId, null, dataArr.toString()); - } - }); - } - - public void queryPurchase(String funId) { - billingClient.queryPurchasesAsync( - QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(), - (billingResult, purchases) -> { - // Process the result - final JSONArray dataArr = new JSONArray(); - boolean hasErr = false; - for (Purchase purchase : purchases) { - try { - handlePurchase(dataArr, purchase); - } catch (JSONException e) { - hasErr = true; - break; - } - } - if (hasErr) { - purchaseUpdateCb(funId, "error parse purchase data", null); - } else { - purchaseUpdateCb(funId, null, dataArr.toString()); - } - }); - } - - public void buyOne(String funId, String productId, String orderId) { - if (mFunId != null && !mFunId.isEmpty()) { - purchaseUpdateCb(funId, "another purchase is in progress", null); - return; - } - if (!skuDetailsMap.containsKey(productId)) { - purchaseUpdateCb(funId, "product with : "+productId+ " not found", null); - return; - } - ProductDetails productDetails = skuDetailsMap.get(productId); - // Set the parameters for the offer that will be presented - // in the billing flow creating separate productDetailsParamsList variable - List productDetailsParamsList = Collections - .singletonList(BillingFlowParams.ProductDetailsParams.newBuilder() - .setProductDetails(productDetails) - .build()); - - BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() - .setProductDetailsParamsList(productDetailsParamsList) - .setObfuscatedAccountId(orderId) - .setObfuscatedProfileId(orderId) - .build(); - - // Launch the billing flow - this.mFunId = funId; - MainActivity.app.runOnUiThread(() -> { - billingClient.launchBillingFlow((Activity) mContext, billingFlowParams); - }); - } -} diff --git a/app/src/com/jc/jcfw/google/PayClient.kt b/app/src/com/jc/jcfw/google/PayClient.kt new file mode 100644 index 0000000..37757ea --- /dev/null +++ b/app/src/com/jc/jcfw/google/PayClient.kt @@ -0,0 +1,250 @@ +package com.jc.jcfw.google + +import android.app.Activity +import android.content.Context +import android.util.Log +import com.android.billingclient.api.BillingClient +import com.android.billingclient.api.BillingClientStateListener +import com.android.billingclient.api.BillingFlowParams +import com.android.billingclient.api.BillingFlowParams.ProductDetailsParams +import com.android.billingclient.api.BillingResult +import com.android.billingclient.api.ProductDetails +import com.android.billingclient.api.Purchase +import com.android.billingclient.api.PurchasesUpdatedListener +import com.android.billingclient.api.QueryProductDetailsParams +import com.android.billingclient.api.QueryPurchasesParams +import com.ctf.games.release.MainActivity +import com.jc.jcfw.JcSDK +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.util.concurrent.ConcurrentHashMap + +class PayClient : Activity(), PurchasesUpdatedListener { + private var mContext: Context? = null + private var mFunId: String? = null + fun init(context: Context?) { + mContext = context + skuDetailsMap = ConcurrentHashMap() + billingClient = + BillingClient.newBuilder(context!!).enablePendingPurchases().setListener(this).build() + connectToPlay() + } + + private fun connectToPlay() { + billingClient!!.startConnection(object : BillingClientStateListener { + override fun onBillingSetupFinished(billingResult: BillingResult) { + Log.i(TAG, "onBillingSetupFinished, response code: " + billingResult.responseCode) + if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) { + // The BillingClient is ready. You can query purchases here. + Log.i(TAG, "BillingClient is ready") + } else { + Log.i(TAG, "error init BillingClient with error:: " + billingResult.responseCode) + } + } + + override fun onBillingServiceDisconnected() { + // Try to restart the connection on the next request to + // Google Play by calling the startConnection() method. + connectToPlay() + } + }) + } + + @Throws(JSONException::class) + fun handlePurchase(dataArr: JSONArray, purchase: Purchase): JSONArray { + if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED // || purchase.getPurchaseState() == Purchase.PurchaseState.PENDING + ) { + // Acknowledge purchase and grant the item to the user + // Grant entitlement to the user. + Log.i(TAG, "handlePurchase:" + purchase.originalJson) + Log.i(TAG, "purchase sign:" + purchase.signature) + if (!purchase.isAcknowledged && purchase.products.size > 0) { + // consumables 消耗型 + val data = JSONObject() + data.put("id", purchase.products[0]) + data.put("token", purchase.purchaseToken) + dataArr.put(data) + } + } + return dataArr + } + + override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List?) { + Log.i(TAG, "onPurchasesUpdated with status: " + billingResult.responseCode) + if (billingResult.responseCode == BillingClient.BillingResponseCode.OK + && purchases != null + ) { + val dataArr = JSONArray() + var hasErr = false + for (purchase in purchases) { + try { + handlePurchase(dataArr, purchase) + } catch (e: JSONException) { + hasErr = true + break + } + } + if (hasErr) { + purchaseUpdateCb(null, "error parse purchase data", null) + } else { + purchaseUpdateCb(null, null, dataArr.toString()) + } + } else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) { + purchaseUpdateCb(null, "user cancel buy", null) + } else { + var errmsg = billingResult.debugMessage + if (errmsg.isEmpty()) { + errmsg = "other error" + } + purchaseUpdateCb(null, errmsg, null) + } + } + + private fun purchaseUpdateCb(funId: String?, error: String?, dataStr: String?) { + if (funId == null || funId.isEmpty()) { + if (mFunId != null && !mFunId!!.isEmpty()) { + runOnUiThread { JcSDK.nativeCb(mFunId, error, dataStr) } + mFunId = null + } + } else { + runOnUiThread { JcSDK.nativeCb(funId, error, dataStr) } + } + } + + private fun parseProductDetails(dataArr: JSONArray, skuDetails: ProductDetails): Boolean { + val data = JSONObject() + return try { + data.put("name", skuDetails.title) + data.put("description", skuDetails.description) + data.put("id", skuDetails.productId) + data.put("type", skuDetails.productType) + if (skuDetails.productType == BillingClient.ProductType.INAPP) { + data.put( + "currencyCode", + skuDetails.oneTimePurchaseOfferDetails!!.priceCurrencyCode + ) + data.put("priceValue", skuDetails.oneTimePurchaseOfferDetails!!.priceAmountMicros) + data.put("priceShow", skuDetails.oneTimePurchaseOfferDetails!!.formattedPrice) + } + dataArr.put(data) + true + } catch (e: JSONException) { + e.printStackTrace() + false + } + } + + fun queryProductList(funId: String?, productIds: List) { + val productList: MutableList = ArrayList() + for (productId in productIds) { + productList.add( + QueryProductDetailsParams.Product.newBuilder() + .setProductId(productId!!) + .setProductType(BillingClient.ProductType.INAPP) + .build() + ) + } + val params = QueryProductDetailsParams.newBuilder() + .setProductList(productList) + .build() + billingClient!!.queryProductDetailsAsync( + params + ) { billingResult: BillingResult?, productDetailsList: List -> + // Process the result + val pMap: MutableMap = HashMap() + for (details in productDetailsList) { + skuDetailsMap!![details.productId] = details + pMap[details.productId] = details + } + val dataArr = JSONArray() + var hasErr = false + for ((_, skuDetails) in pMap) { + if (!parseProductDetails(dataArr, skuDetails)) { + hasErr = true + break + } + } + if (hasErr) { + purchaseUpdateCb(funId, "parse product detail json error", null) + } else { + purchaseUpdateCb(funId, null, dataArr.toString()) + } + } + } + + fun queryPurchase(funId: String?) { + billingClient!!.queryPurchasesAsync( + QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build() + ) { billingResult: BillingResult?, purchases: List -> + // Process the result + val dataArr = JSONArray() + var hasErr = false + for (purchase in purchases) { + try { + handlePurchase(dataArr, purchase) + } catch (e: JSONException) { + hasErr = true + break + } + } + if (hasErr) { + purchaseUpdateCb(funId, "error parse purchase data", null) + } else { + purchaseUpdateCb(funId, null, dataArr.toString()) + } + } + } + + fun buyOne(funId: String?, productId: String, orderId: String?) { + if (mFunId != null && !mFunId!!.isEmpty()) { + purchaseUpdateCb(funId, "another purchase is in progress", null) + return + } + if (!skuDetailsMap!!.containsKey(productId)) { + purchaseUpdateCb(funId, "product with : $productId not found", null) + return + } + val productDetails = skuDetailsMap!![productId] + // Set the parameters for the offer that will be presented + // in the billing flow creating separate productDetailsParamsList variable + val productDetailsParamsList = listOf( + ProductDetailsParams.newBuilder() + .setProductDetails(productDetails!!) + .build() + ) + val billingFlowParams = BillingFlowParams.newBuilder() + .setProductDetailsParamsList(productDetailsParamsList) + .setObfuscatedAccountId(orderId!!) + .setObfuscatedProfileId(orderId) + .build() + + // Launch the billing flow + mFunId = funId + MainActivity.app!!.runOnUiThread { + billingClient!!.launchBillingFlow( + (mContext as Activity?)!!, billingFlowParams + ) + } + } + + companion object { + private const val TAG = "GooglePayClient" + + @Volatile + private var mInstance: PayClient? = null + private var billingClient: BillingClient? = null + private var skuDetailsMap: ConcurrentHashMap? = null + val instance: PayClient? + get() { + if (null == mInstance) { + synchronized(PayClient::class.java) { + if (null == mInstance) { + mInstance = PayClient() + } + } + } + return mInstance + } + } +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/DriveUtils.java b/app/src/com/jc/jcfw/util/DriveUtils.java deleted file mode 100644 index 6329b70..0000000 --- a/app/src/com/jc/jcfw/util/DriveUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -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(); - } -} diff --git a/app/src/com/jc/jcfw/util/DriveUtils.kt b/app/src/com/jc/jcfw/util/DriveUtils.kt new file mode 100644 index 0000000..4a1db6d --- /dev/null +++ b/app/src/com/jc/jcfw/util/DriveUtils.kt @@ -0,0 +1,96 @@ +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 java.io.ByteArrayOutputStream +import java.io.File +import java.io.IOException +import java.io.OutputStream + +object DriveUtils { + private val TAG = DriveUtils::class.java.simpleName + fun generateService(credential: GoogleAccountCredential?, appName: String?): Drive { + return Drive.Builder( + AndroidHttp.newCompatibleTransport(), + AndroidJsonFactory.getDefaultInstance(), + credential + ) + .setApplicationName(appName) + .build() + } + + /** + * query app file by filename + * + * @param service + * @param fileName + * @throws IOException + */ + fun queryOneAppFile(service: Drive, fileName: String): String { + var querySuccess = false + var fileId = "" + while (!querySuccess) { + try { + val files = service.files().list() + .setSpaces("appDataFolder") + .setFields("nextPageToken, files(id, name)") + .setPageSize(100) + .execute() + querySuccess = true + for (file in files.files) { + Log.i(TAG, String.format("Found file: %s (%s)\n", file.name, file.id)) + if (file.name == fileName) { + fileId = file.id + break + } + } + } catch (e: IOException) { + Log.i(TAG, "error query file from drive") + } + } + return fileId + } + + /** + * download one file from drive + * + * @param service + * @param fileId + * @throws IOException + */ + @Throws(IOException::class) + fun downloadFile(service: Drive, fileId: String?): String { + val outputStream: OutputStream = ByteArrayOutputStream() + service.files()[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 + */ + @Throws(IOException::class) + fun uploadAppFile(service: Drive, filePath: File, fileType: String?): String { + val fileName = filePath.name + val fileMetadata = com.google.api.services.drive.model.File() + fileMetadata.name = fileName + fileMetadata.parents = listOf("appDataFolder") + // "application/json" + val mediaContent = FileContent(fileType, filePath) + val file = service.files().create(fileMetadata, mediaContent) + .setFields("id") + .execute() + Log.i(TAG, String.format("%s upload success, File ID: %s", fileName, file.id)) + return file.id + } +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/DriverApiUtils.java b/app/src/com/jc/jcfw/util/DriverApiUtils.java deleted file mode 100644 index 6c88911..0000000 --- a/app/src/com/jc/jcfw/util/DriverApiUtils.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.jc.jcfw.util; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -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 static final String driveApiUploadBase = "https://www.googleapis.com/upload/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 String uploadFile(java.io.File filePath, String fileType) throws IOException { - OkHttpClient client = new OkHttpClient().newBuilder() - .build(); - String fileName = filePath.getName(); - String optionStr = "{\"name\":\""+fileName+"\",\"parents\":[\"appDataFolder\"]}"; - RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) - .addFormDataPart("", "upload-options.json", - RequestBody.create(optionStr, MediaType.parse("application/json"))) - .addFormDataPart("", fileName, - RequestBody.create(filePath, MediaType.parse("application/octet-stream"))) - .build(); - Request request = new Request.Builder() - .url(driveApiUploadBase + "?uploadType=multipart") - .post(body) - .addHeader("Content-Type", fileType) - .addHeader("Authorization", "Bearer " + token) - .build(); - Response response = client.newCall(request).execute(); - return response.body().string(); - } -} diff --git a/app/src/com/jc/jcfw/util/DriverApiUtils.kt b/app/src/com/jc/jcfw/util/DriverApiUtils.kt new file mode 100644 index 0000000..9626f7a --- /dev/null +++ b/app/src/com/jc/jcfw/util/DriverApiUtils.kt @@ -0,0 +1,98 @@ +package com.jc.jcfw.util + + +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Request.Builder +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.io.File +import java.io.IOException + +class DriverApiUtils { + private val TAG = javaClass.simpleName + var token = "" + + constructor() {} + constructor(token: String) { + this.token = token + } + + @Throws(IOException::class, JSONException::class) + fun fileList(): JSONArray { + val client = OkHttpClient().newBuilder() + .build() + val request: Request = Builder() + .url(driveApiBase + "?spaces=appDataFolder&fields=files(id, name, modifiedTime)") + .get() + .addHeader("Authorization", "Bearer $token") + .build() + client.newCall(request).execute().use { response -> + val resStr = response.body!!.string() + val resJson = JSONObject(resStr) + return resJson.getJSONArray("files") + } + } + + @Throws(IOException::class, JSONException::class) + fun queryOneAppFile(fileName: String): String { + val fileList = fileList() + for (i in 0 until fileList.length()) { + val file = fileList.getJSONObject(i) + if (file.getString("name") == fileName) { + return file.getString("id") + } + } + return "" + } + + @Throws(IOException::class) + fun fileInfo(fileId: String?): String { + val client = OkHttpClient().newBuilder() + .build() + val request: Request = Builder() + .url(String.format("%s/%s?alt=media", driveApiBase, fileId)) + .get() + .addHeader("Authorization", "Bearer $token") + .build() + client.newCall(request).execute().use { response -> return response.body!!.string() } + } + + @Throws(IOException::class) + fun uploadFile(filePath: File, fileType: String): String { + val client = OkHttpClient().newBuilder() + .build() + val fileName = filePath.name + val optionStr = "{\"name\":\"$fileName\",\"parents\":[\"appDataFolder\"]}" + val body: RequestBody = MultipartBody.Builder().setType(MultipartBody.FORM) + .addFormDataPart( + "", "upload-options.json", + optionStr.toRequestBody("application/json".toMediaTypeOrNull()) + ) + .addFormDataPart( + "", fileName, + filePath.asRequestBody("application/octet-stream".toMediaTypeOrNull()) + ) + .build() + val request: Request = Builder() + .url("$driveApiUploadBase?uploadType=multipart") + .post(body) + .addHeader("Content-Type", fileType) + .addHeader("Authorization", "Bearer $token") + .build() + val response = client.newCall(request).execute() + return response.body!!.string() + } + + companion object { + private const val driveApiBase = "https://www.googleapis.com/drive/v3/files" + private const val driveApiUploadBase = "https://www.googleapis.com/upload/drive/v3/files" + } +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/FileUtils.java b/app/src/com/jc/jcfw/util/FileUtils.java deleted file mode 100644 index 842b942..0000000 --- a/app/src/com/jc/jcfw/util/FileUtils.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.jc.jcfw.util; - -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Build; -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(); - /** - * check if path specificed exists, create it if not exists - * - * @param fileName path - * @return TRUE or FALSE - */ - public static boolean fileIsExist(String fileName) { - File file = new File(fileName); - if (file.exists()) - return true; - else { - return file.mkdirs(); - } - } - - 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 - */ - public static String getPath(Context context) { - String fileName = ""; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - fileName = context.getExternalFilesDir("").getAbsolutePath() + "/current/"; - } else { - if ("Xiaomi".equalsIgnoreCase(Build.BRAND)) { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/"; - } else if ("HUAWEI".equalsIgnoreCase(Build.BRAND)) { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/"; - } else if ("HONOR".equalsIgnoreCase(Build.BRAND)) { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/"; - } else if ("OPPO".equalsIgnoreCase(Build.BRAND)) { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/"; - } else if ("vivo".equalsIgnoreCase(Build.BRAND)) { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/"; - } else if ("samsung".equalsIgnoreCase(Build.BRAND)) { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/"; - } else { - fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/"; - } - } - File file = new File(fileName); - if (file.mkdirs()) { - return fileName; - } - return fileName; - } - - public static String insertImageIntoGallery(Context activity, Bitmap source, String filename, String title) { - ContentResolver cr = activity.getContentResolver(); - ContentValues values = new ContentValues(); - values.put(MediaStore.Images.Media.TITLE, title); - values.put(MediaStore.Images.Media.DISPLAY_NAME, title); - values.put(MediaStore.Images.Media.DESCRIPTION, title); - values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - // Add the date meta data to ensure the image is added at the front of the gallery - values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); - values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - values.put(MediaStore.Video.Media.IS_PENDING, 1); - } - - Uri url = null; - String stringUrl = null; /* value to be returned */ - - try { - url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); - - if (source != null) { - OutputStream imageOut = cr.openOutputStream(url); - try { - source.compress(Bitmap.CompressFormat.JPEG, 100, imageOut); - } finally { - imageOut.close(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - values.put(MediaStore.Video.Media.IS_PENDING, 0); - cr.update(url, values, null, null); - } - } - } else { - cr.delete(url, null, null); - return storeToAlternateSd(activity, source, filename); - // url = null; - } - } catch (Exception e) { - if (url != null) { - cr.delete(url, null, null); - // url = null; - } - return storeToAlternateSd(activity, source, filename); - } - if (url != null) { - stringUrl = url.toString(); - } - - return stringUrl; - } - - /** - * If we have issues saving into our MediaStore, save it directly to our SD card. We can then interact with this file - * directly, opposed to pulling from the MediaStore. Again, this is a backup method if things don't work out as we - * would expect (seeing as most devices will have a MediaStore). - * - * @param src - * @return - the file's path - */ - private static String storeToAlternateSd(Context activity, Bitmap src, String filename){ - if(src == null) - return null; - - String sdCardDirectory = getPath(activity); - File image = new File(sdCardDirectory, filename + ".jpg"); - try { - FileOutputStream imageOut = new FileOutputStream(image); - src.compress(Bitmap.CompressFormat.JPEG, 100, imageOut); - imageOut.close(); - return image.getAbsolutePath(); - } catch (IOException ex) { - ex.printStackTrace(); - return null; - } - } - /* - * save bitmap to system gallery - */ - public static String saveBitmap(Context activity, String oid, Bitmap bitmap) { - String title = "wallet_key_" + oid; - String imageName = "wallet_key_" + oid; - String uri = insertImageIntoGallery(activity, bitmap, imageName, title); - Log.i(TAG, "save image success: " + uri); - return uri; - } - - - public static Bitmap loadImgData(Context activity, String oid) { - Uri uri = readImageFromGallery(activity, oid); - Bitmap data; - if (uri != null) { - try { - data = MediaStore.Images.Media.getBitmap(activity.getContentResolver(),uri); - } catch (IOException e) { - data = readImageFromExt(activity, oid); - } - } else { - data = readImageFromExt(activity, oid); - } - - return data; - } - - public static Bitmap readImageFromExt(Context activity, String oid) { - String sdCardDirectory = getPath(activity); - String imageName = "wallet_key_" + oid; - File file = new File(sdCardDirectory, imageName + ".jpg"); - if (!file.exists()) { - return null; - } - Bitmap bitmap = null; - try { - bitmap = BitmapFactory.decodeFile(file.getPath()); - } catch (Exception e) { - e.printStackTrace(); - } - return bitmap; - } - - public static Uri readImageFromGallery(Context activity, String oid) { - String filename = "wallet_key_" + oid; - Uri uri; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - uri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL); - } else { - uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } - Uri result = null; - String[] projection = {MediaStore.Images.Media._ID, - MediaStore.Images.Media.DATA, - MediaStore.Images.Media.DISPLAY_NAME}; - final String orderBy = MediaStore.Images.Media.DATE_ADDED; - Cursor cursor = activity.getContentResolver().query(uri, projection, null, null, orderBy + " DESC"); - String imageName = "wallet_key_" + oid; - if (cursor != null) { - int nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME); - int idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID); - int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA); - while (cursor.moveToNext()) { - String name = cursor.getString(nameColumn); - long id = cursor.getLong(idColumn); - Log.i(TAG, "img name: " + name + " id: " + id); - if (name.contains(imageName)) { - String data = cursor.getString(dataColumn); - result = ContentUris.withAppendedId(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL), id); - Log.i(TAG, "img name: " + name + " id: " + id + " data:" + data); - break; - } - } - cursor.close(); - } - return result; - } -} diff --git a/app/src/com/jc/jcfw/util/FileUtils.kt b/app/src/com/jc/jcfw/util/FileUtils.kt new file mode 100644 index 0000000..4ef85d8 --- /dev/null +++ b/app/src/com/jc/jcfw/util/FileUtils.kt @@ -0,0 +1,237 @@ +package com.jc.jcfw.util + +import android.content.ContentUris +import android.content.ContentValues +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.net.Uri +import android.os.Build +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.FileOutputStream +import java.io.IOException +import java.io.RandomAccessFile + +object FileUtils { + private val TAG = FileUtils::class.java.simpleName + + /** + * check if path specificed exists, create it if not exists + * + * @param fileName path + * @return TRUE or FALSE + */ + fun fileIsExist(fileName: String?): Boolean { + val file = File(fileName) + return if (file.exists()) true else { + file.mkdirs() + } + } + + @Throws(IOException::class) + fun writeFile(filePath: File?, content: String) { + val out = FileOutputStream(filePath) + out.write(content.toByteArray()) + out.close() + } + + @Throws(IOException::class, JSONException::class) + fun readJsonFromFile(filePath: File?): JSONObject { + val f = RandomAccessFile(filePath, "r") + val bytes = ByteArray(f.length().toInt()) + f.readFully(bytes) + f.close() + return JSONObject(String(bytes)) + } + + /** + * get image base path of external storage + */ + fun getPath(context: Context): String { + var fileName = "" + fileName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + context.getExternalFilesDir("")!!.absolutePath + "/current/" + } else { + if ("Xiaomi".equals(Build.BRAND, ignoreCase = true)) { + Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + } else if ("HUAWEI".equals(Build.BRAND, ignoreCase = true)) { + Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + } else if ("HONOR".equals(Build.BRAND, ignoreCase = true)) { + Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + } else if ("OPPO".equals(Build.BRAND, ignoreCase = true)) { + Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + } else if ("vivo".equals(Build.BRAND, ignoreCase = true)) { + Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + } else if ("samsung".equals(Build.BRAND, ignoreCase = true)) { + Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + } else { + Environment.getExternalStorageDirectory().path + "/DCIM/" + } + } + val file = File(fileName) + return if (file.mkdirs()) { + fileName + } else fileName + } + + fun insertImageIntoGallery( + activity: Context, + source: Bitmap?, + filename: String, + title: String? + ): String? { + val cr = activity.contentResolver + val values = ContentValues() + values.put(MediaStore.Images.Media.TITLE, title) + values.put(MediaStore.Images.Media.DISPLAY_NAME, title) + values.put(MediaStore.Images.Media.DESCRIPTION, title) + values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") + // Add the date meta data to ensure the image is added at the front of the gallery + values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()) + values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + values.put(MediaStore.Video.Media.IS_PENDING, 1) + } + var url: Uri? = null + var stringUrl: String? = null /* value to be returned */ + try { + url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values) + if (source != null) { + val imageOut = cr.openOutputStream(url!!) + try { + source.compress(Bitmap.CompressFormat.JPEG, 100, imageOut) + } finally { + imageOut!!.close() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + values.put(MediaStore.Video.Media.IS_PENDING, 0) + cr.update(url, values, null, null) + } + } + } else { + cr.delete(url!!, null, null) + return storeToAlternateSd(activity, source, filename) + // url = null; + } + } catch (e: Exception) { + if (url != null) { + cr.delete(url, null, null) + // url = null; + } + return storeToAlternateSd(activity, source, filename) + } + if (url != null) { + stringUrl = url.toString() + } + return stringUrl + } + + /** + * If we have issues saving into our MediaStore, save it directly to our SD card. We can then interact with this file + * directly, opposed to pulling from the MediaStore. Again, this is a backup method if things don't work out as we + * would expect (seeing as most devices will have a MediaStore). + * + * @param src + * @return - the file's path + */ + private fun storeToAlternateSd(activity: Context, src: Bitmap?, filename: String): String? { + if (src == null) return null + val sdCardDirectory = getPath(activity) + val image = File(sdCardDirectory, "$filename.jpg") + return try { + val imageOut = FileOutputStream(image) + src.compress(Bitmap.CompressFormat.JPEG, 100, imageOut) + imageOut.close() + image.absolutePath + } catch (ex: IOException) { + ex.printStackTrace() + null + } + } + + /* + * save bitmap to system gallery + */ + fun saveBitmap(activity: Context, oid: String, bitmap: Bitmap?): String? { + val title = "wallet_key_$oid" + val imageName = "wallet_key_$oid" + val uri = insertImageIntoGallery(activity, bitmap, imageName, title) + Log.i(TAG, "save image success: $uri") + return uri + } + + fun loadImgData(activity: Context, oid: String): Bitmap? { + val uri = readImageFromGallery(activity, oid) + val data: Bitmap? + data = if (uri != null) { + try { + MediaStore.Images.Media.getBitmap(activity.contentResolver, uri) + } catch (e: IOException) { + readImageFromExt(activity, oid) + } + } else { + readImageFromExt(activity, oid) + } + return data + } + + fun readImageFromExt(activity: Context, oid: String): Bitmap? { + val sdCardDirectory = getPath(activity) + val imageName = "wallet_key_$oid" + val file = File(sdCardDirectory, "$imageName.jpg") + if (!file.exists()) { + return null + } + var bitmap: Bitmap? = null + try { + bitmap = BitmapFactory.decodeFile(file.path) + } catch (e: Exception) { + e.printStackTrace() + } + return bitmap + } + + fun readImageFromGallery(activity: Context, oid: String): Uri? { + val filename = "wallet_key_$oid" + val uri: Uri + uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL) + } else { + MediaStore.Images.Media.EXTERNAL_CONTENT_URI + } + var result: Uri? = null + val projection = arrayOf( + MediaStore.Images.Media._ID, + MediaStore.Images.Media.DATA, + MediaStore.Images.Media.DISPLAY_NAME + ) + val orderBy = MediaStore.Images.Media.DATE_ADDED + val cursor = activity.contentResolver.query(uri, projection, null, null, "$orderBy DESC") + val imageName = "wallet_key_$oid" + if (cursor != null) { + val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) + val idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID) + val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA) + while (cursor.moveToNext()) { + val name = cursor.getString(nameColumn) + val id = cursor.getLong(idColumn) + Log.i(TAG, "img name: $name id: $id") + if (name.contains(imageName)) { + val data = cursor.getString(dataColumn) + result = ContentUris.withAppendedId( + MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL), + id + ) + Log.i(TAG, "img name: $name id: $id data:$data") + break + } + } + cursor.close() + } + return result + } +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/JsonUtils.java b/app/src/com/jc/jcfw/util/JsonUtils.java deleted file mode 100644 index 2c9d2fc..0000000 --- a/app/src/com/jc/jcfw/util/JsonUtils.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.jc.jcfw.util; - -import android.os.Bundle; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.Iterator; - -public class JsonUtils { - public static Bundle convertJsonToBundle(String jsonString) throws JSONException { - Bundle bundle = new Bundle(); - JSONObject jsonObject = new JSONObject(jsonString); - traverseJsonObject(jsonObject, bundle); - return bundle; - } - - public static void traverseJsonObject(JSONObject jsonObject, Bundle bundle) throws JSONException { - Iterator keys = jsonObject.keys(); - while (keys.hasNext()) { - String key = keys.next(); - Object value = jsonObject.get(key); -// if (value instanceof JSONObject) { -// traverseJsonObject((JSONObject) value, bundle); -// } else { -// bundle.putString(key, value.toString()); -// } - bundle.putString(key, value.toString()); - } - } -} diff --git a/app/src/com/jc/jcfw/util/JsonUtils.kt b/app/src/com/jc/jcfw/util/JsonUtils.kt new file mode 100644 index 0000000..387b563 --- /dev/null +++ b/app/src/com/jc/jcfw/util/JsonUtils.kt @@ -0,0 +1,30 @@ +package com.jc.jcfw.util + +import android.os.Bundle +import org.json.JSONException +import org.json.JSONObject + +object JsonUtils { + @Throws(JSONException::class) + fun convertJsonToBundle(jsonString: String?): Bundle { + val bundle = Bundle() + val jsonObject = JSONObject(jsonString) + traverseJsonObject(jsonObject, bundle) + return bundle + } + + @Throws(JSONException::class) + fun traverseJsonObject(jsonObject: JSONObject, bundle: Bundle) { + val keys = jsonObject.keys() + while (keys.hasNext()) { + val key = keys.next() + val value = jsonObject[key] + // if (value instanceof JSONObject) { +// traverseJsonObject((JSONObject) value, bundle); +// } else { +// bundle.putString(key, value.toString()); +// } + bundle.putString(key, value.toString()) + } + } +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/SharedPreferencesHelper.java b/app/src/com/jc/jcfw/util/SharedPreferencesHelper.java deleted file mode 100644 index 406763a..0000000 --- a/app/src/com/jc/jcfw/util/SharedPreferencesHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.jc.jcfw.util; - -import android.content.Context; -import android.content.SharedPreferences; - -import java.util.Map; - -public class SharedPreferencesHelper { - private final SharedPreferences sharedPreferences; - private SharedPreferences.Editor editor; - - public SharedPreferencesHelper(Context context, String FILE_NAME) { - sharedPreferences = context.getSharedPreferences(FILE_NAME, - Context.MODE_PRIVATE); - editor = sharedPreferences.edit(); - } - - public void put(String key, Object object) { - if (object instanceof String) { - editor.putString(key, (String) object); - } else if (object instanceof Integer) { - editor.putInt(key, (Integer) object); - } else if (object instanceof Boolean) { - editor.putBoolean(key, (Boolean) object); - } else if (object instanceof Float) { - editor.putFloat(key, (Float) object); - } else if (object instanceof Long) { - editor.putLong(key, (Long) object); - } else { - editor.putString(key, object.toString()); - } - editor.commit(); - } - - public Object getSharedPreference(String key, Object defaultObject) { - if (defaultObject instanceof String) { - return sharedPreferences.getString(key, (String) defaultObject); - } else if (defaultObject instanceof Integer) { - return sharedPreferences.getInt(key, (Integer) defaultObject); - } else if (defaultObject instanceof Boolean) { - return sharedPreferences.getBoolean(key, (Boolean) defaultObject); - } else if (defaultObject instanceof Float) { - return sharedPreferences.getFloat(key, (Float) defaultObject); - } else if (defaultObject instanceof Long) { - return sharedPreferences.getLong(key, (Long) defaultObject); - } else { - return sharedPreferences.getString(key, null); - } - } - - - public void remove(String key) { - editor.remove(key); - editor.commit(); - } - - - public void clear() { - editor.clear(); - editor.commit(); - } - - - public Boolean contain(String key) { - return sharedPreferences.contains(key); - } - - - public Map getAll() { - return sharedPreferences.getAll(); - } -} diff --git a/app/src/com/jc/jcfw/util/SharedPreferencesHelper.kt b/app/src/com/jc/jcfw/util/SharedPreferencesHelper.kt new file mode 100644 index 0000000..e674061 --- /dev/null +++ b/app/src/com/jc/jcfw/util/SharedPreferencesHelper.kt @@ -0,0 +1,67 @@ +package com.jc.jcfw.util + +import android.content.Context +import android.content.SharedPreferences + +class SharedPreferencesHelper(context: Context, FILE_NAME: String?) { + private val sharedPreferences: SharedPreferences + private val editor: SharedPreferences.Editor + + init { + sharedPreferences = context.getSharedPreferences( + FILE_NAME, + Context.MODE_PRIVATE + ) + editor = sharedPreferences.edit() + } + + fun put(key: String?, `object`: Any) { + if (`object` is String) { + editor.putString(key, `object`) + } else if (`object` is Int) { + editor.putInt(key, `object`) + } else if (`object` is Boolean) { + editor.putBoolean(key, `object`) + } else if (`object` is Float) { + editor.putFloat(key, `object`) + } else if (`object` is Long) { + editor.putLong(key, `object`) + } else { + editor.putString(key, `object`.toString()) + } + editor.commit() + } + + fun getSharedPreference(key: String?, defaultObject: Any?): Any? { + return if (defaultObject is String) { + sharedPreferences.getString(key, defaultObject as String?) + } else if (defaultObject is Int) { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } else if (defaultObject is Boolean) { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } else if (defaultObject is Float) { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } else if (defaultObject is Long) { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } else { + sharedPreferences.getString(key, null) + } + } + + fun remove(key: String?) { + editor.remove(key) + editor.commit() + } + + fun clear() { + editor.clear() + editor.commit() + } + + fun contain(key: String?): Boolean { + return sharedPreferences.contains(key) + } + + val all: Map + get() = sharedPreferences.all +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/ThreadUtils.java b/app/src/com/jc/jcfw/util/ThreadUtils.java deleted file mode 100644 index 513e999..0000000 --- a/app/src/com/jc/jcfw/util/ThreadUtils.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.jc.jcfw.util; - -import android.os.Handler; -import android.os.Looper; - -public class ThreadUtils { - /** - * check if current thread is main thread - * - * @return - */ - public static boolean isMainThread() { - return Looper.getMainLooper() == Looper.myLooper(); - } - - public static void runInMain(Runnable action) { - if (ThreadUtils.isMainThread()) { - action.run(); - } else { - Handler mainHandler = new Handler(Looper.getMainLooper()); - mainHandler.post(action); - } - } -} diff --git a/app/src/com/jc/jcfw/util/ThreadUtils.kt b/app/src/com/jc/jcfw/util/ThreadUtils.kt new file mode 100644 index 0000000..8925dea --- /dev/null +++ b/app/src/com/jc/jcfw/util/ThreadUtils.kt @@ -0,0 +1,23 @@ +package com.jc.jcfw.util + +import android.os.Handler +import android.os.Looper + +object ThreadUtils { + /** + * check if current thread is main thread + * + * @return + */ + private val isMainThread: Boolean + get() = Looper.getMainLooper() == Looper.myLooper() + + fun runInMain(action: Runnable) { + if (isMainThread) { + action.run() + } else { + val mainHandler = Handler(Looper.getMainLooper()) + mainHandler.post(action) + } + } +} \ No newline at end of file diff --git a/app/src/com/jc/jcfw/util/UIUtils.java b/app/src/com/jc/jcfw/util/UIUtils.java deleted file mode 100644 index b436b82..0000000 --- a/app/src/com/jc/jcfw/util/UIUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.jc.jcfw.util; - -import android.content.Context; -import android.widget.Toast; - -import androidx.annotation.MainThread; - -import com.ctf.games.release.dialog.QRCodeActivity; - -public class UIUtils { - private static Toast toast; - - @MainThread - public static void showToastReal(Context context,String text) { - if (toast == null) { - toast = Toast.makeText(context, text, Toast.LENGTH_SHORT); - } else { - toast.setDuration(Toast.LENGTH_SHORT); - toast.setText(text); - } - toast.show(); - } - public static void showToast(Context context, String text) { - ThreadUtils.runInMain(() -> showToastReal(context, text)); - } - @MainThread - public static void showQRCodeReal(Context context, String str, String title) { - QRCodeActivity qrCodeActivity = new QRCodeActivity(context); - qrCodeActivity.showQRCode(str, title); - qrCodeActivity.show(); - } - - public static void showQRCode(Context context, String str, String title) { - ThreadUtils.runInMain(() -> showQRCodeReal(context, str, title)); - } -} diff --git a/app/src/com/jc/jcfw/util/UIUtils.kt b/app/src/com/jc/jcfw/util/UIUtils.kt new file mode 100644 index 0000000..33b1a6c --- /dev/null +++ b/app/src/com/jc/jcfw/util/UIUtils.kt @@ -0,0 +1,35 @@ +package com.jc.jcfw.util + +import android.content.Context +import android.widget.Toast +import androidx.annotation.MainThread +import com.ctf.games.release.dialog.QRCodeActivity + +object UIUtils { + private var toast: Toast? = null + @MainThread + fun showToastReal(context: Context?, text: String?) { + if (toast == null) { + toast = Toast.makeText(context, text, Toast.LENGTH_SHORT) + } else { + toast!!.duration = Toast.LENGTH_SHORT + toast!!.setText(text) + } + toast!!.show() + } + + fun showToast(context: Context?, text: String?) { + ThreadUtils.runInMain { showToastReal(context, text) } + } + + @MainThread + fun showQRCodeReal(context: Context?, str: String?, title: String?) { + val qrCodeActivity = QRCodeActivity(context!!) + qrCodeActivity.showQRCode(str, title) + qrCodeActivity.show() + } + + fun showQRCode(context: Context?, str: String?, title: String?) { + ThreadUtils.runInMain { showQRCodeReal(context, str, title) } + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 486139b..ed9fd06 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. apply from: "config.gradle" buildscript { + ext.kotlin_version = '1.7.20' repositories { google() jcenter() @@ -15,6 +16,7 @@ buildscript { classpath 'com.google.gms:google-services:4.3.15' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.6' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/res/values/strings.xml b/res/values/strings.xml index c3673d0..67e6858 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,5 +1,5 @@ - CEBG + CF Game view Scan QRCode need camera permission QRCode