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