打包成功
@@ -1,16 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<application android:allowBackup="true" android:label="@string/app_name" android:usesCleartextTraffic="true" android:icon="@mipmap/ic_launcher" android:resizeableActivity="true">
|
||||
<meta-data android:name="android.app.lib_name" android:value="cocos"/>
|
||||
<activity android:name="com.cocos.game.AppActivity" android:screenOrientation="sensorLandscape" android:configChanges="orientation|keyboardHidden|screenSize|screenLayout|smallestScreenSize" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:launchMode="singleTask" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.cocos.lib.CocosEditBoxActivity" android:configChanges="orientation|keyboardHidden|screenSize|screenLayout|smallestScreenSize" android:screenOrientation="behind" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"/>
|
||||
</application>
|
||||
</manifest>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
<!--<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />-->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<!--Android 13版本适配,细化存储权限-->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_LOGS"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
<!--google pay-->
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
|
||||
<!--Adjust SDK -->
|
||||
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
|
||||
|
||||
<!-- zego sdk ,google play 提包aab、很多机型无法支持蓝牙才移除、但是android6.0会崩溃、影响人数不多、先屏蔽 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<!--适配Android R包可见性 开始-->
|
||||
<queries package="${applicationId}">
|
||||
<intent>
|
||||
<action android:name="android.media.action.IMAGE_CAPTURE">
|
||||
|
||||
</action>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="android.media.action.ACTION_VIDEO_CAPTURE">
|
||||
|
||||
</action>
|
||||
</intent>
|
||||
</queries>
|
||||
<!--适配Android R包可见性 结束-->
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
android:required="true" />
|
||||
|
||||
<application
|
||||
android:name="com.cocos.game.MyApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<!-- 全面屏-->
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="2.1" />
|
||||
|
||||
<!-- Tell CocosNativeActivity the name of our .so -->
|
||||
<meta-data
|
||||
android:name="android.app.lib_name"
|
||||
android:value="cocos" />
|
||||
|
||||
<activity
|
||||
android:name="com.cocos.game.AppActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.cocos.lib.CocosEditBoxActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
|
||||
android:screenOrientation="behind"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
|
||||
|
||||
<!--google firebase-->
|
||||
<service
|
||||
android:name="com.cocos.game.MyFirebaseMessagingService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<!--google play game service-->
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.games.APP_ID"
|
||||
android:value="@string/app_id"
|
||||
tools:replace="android:value" />
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="@integer/google_play_services_version" />
|
||||
|
||||
<!-- Bugly-->
|
||||
<!-- 配置APP ID -->
|
||||
<meta-data
|
||||
android:name="BUGLY_APPID"
|
||||
android:value="@string/Tely_AppId" />
|
||||
<!-- 配置APP版本号 -->
|
||||
<meta-data
|
||||
android:name="BUGLY_APP_VERSION"
|
||||
android:value="@string/Tely_Version" />
|
||||
<!-- 配置APP渠道号 -->
|
||||
<meta-data
|
||||
android:name="BUGLY_APP_CHANNEL"
|
||||
android:value="@string/Tely_Channel" />
|
||||
<!-- 配置Bugly调试模式(true或者false)-->
|
||||
<meta-data
|
||||
android:name="BUGLY_ENABLE_DEBUG"
|
||||
android:value="@bool/Tely_IsDebug" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
||||
RES_PATH = RES_PATH.replace("\\", "/")
|
||||
COCOS_ENGINE_PATH = COCOS_ENGINE_PATH.replace("\\", "/")
|
||||
@@ -35,7 +36,7 @@ android {
|
||||
|
||||
sourceSets.main {
|
||||
java.srcDirs "../src", "src"
|
||||
res.srcDirs "../res", 'res', "${RES_PATH}/proj/res"
|
||||
res.srcDirs "../res", 'res'
|
||||
jniLibs.srcDirs "../libs", 'libs'
|
||||
manifest.srcFile "AndroidManifest.xml"
|
||||
assets.srcDir "${RES_PATH}/data"
|
||||
@@ -116,4 +117,38 @@ dependencies {
|
||||
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.0-beta'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
|
||||
}
|
||||
|
||||
// Google
|
||||
implementation 'com.google.android.gms:play-services-location:21.2.0'
|
||||
implementation 'com.google.android.gms:play-services-auth:21.0.0'
|
||||
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
|
||||
implementation 'com.android.billingclient:billing:7.0.0'
|
||||
implementation 'com.google.android.gms:play-services-games:23.1.0'
|
||||
|
||||
// Firebase
|
||||
implementation platform('com.google.firebase:firebase-bom:32.3.1')
|
||||
implementation 'com.google.firebase:firebase-messaging'
|
||||
implementation 'com.google.firebase:firebase-analytics'
|
||||
|
||||
// Adjust
|
||||
implementation 'com.adjust.sdk:adjust-android:4.38.3'
|
||||
implementation 'com.android.installreferrer:installreferrer:2.2'
|
||||
|
||||
// Bugly
|
||||
implementation 'com.tencent.bugly:crashreport:4.0.0'
|
||||
implementation 'com.tencent.bugly:nativecrashreport:3.9.2'
|
||||
|
||||
// Zego
|
||||
implementation 'im.zego:express-audio:3.18.0'
|
||||
|
||||
// Glide
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
|
||||
// PictureSelector
|
||||
implementation 'io.github.lucksiege:pictureselector:v3.11.1'
|
||||
implementation 'io.github.lucksiege:compress:v3.11.1'
|
||||
implementation 'io.github.lucksiege:ucrop:v3.11.1'
|
||||
implementation 'io.github.lucksiege:camerax:v3.11.1'
|
||||
|
||||
implementation 'org.jetbrains:annotations:15.0'
|
||||
}
|
||||
|
||||
55
android/app/google-services.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "77777777777",
|
||||
"project_id": "dsfdsfsdfsdfsdfsdfsd",
|
||||
"storage_bucket": "dsfdsfsdfsdfsdfsdfsd.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:77777777777:android:0c23bf41a19dbf9031520a",
|
||||
"android_client_info": {
|
||||
"package_name": "com.ddddd.one"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "77777777777-31c3v95gqmgiitcbdbm7g89g2dvbo3g3.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "com.ddddd.one",
|
||||
"certificate_hash": "88c6508575eb69e0170802f358beaa008c14ec1a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "77777777777-mst1841ado9heklp3h3gda3o9at4q8op.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "com.ddddd.one",
|
||||
"certificate_hash": "7db6c283bbdb01a4a21a1755b4c9d52bab58966e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "77777777777-pe7pidhpuc9ohkg5t8aqip7qboire346.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyBnPj5TP43ELp4TAeRKjSmEvPvGKFPI_RA"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "77777777777-pe7pidhpuc9ohkg5t8aqip7qboire346.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
95
android/app/src/com/cocos/game/AdjustUtil.java
Normal file
@@ -0,0 +1,95 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.adjust.sdk.Adjust;
|
||||
import com.adjust.sdk.AdjustAttribution;
|
||||
import com.adjust.sdk.AdjustEvent;
|
||||
import com.adjust.sdk.OnDeviceIdsRead;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class AdjustUtil {
|
||||
|
||||
private static final String TAG = "AdjustUtil";
|
||||
private static AdjustUtil sInstance = null;
|
||||
|
||||
public static AdjustUtil getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new AdjustUtil();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Adjust归因信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getAdjustTrackerToken() {
|
||||
try {
|
||||
AdjustAttribution attribution = Adjust.getAttribution();
|
||||
Log.d(TAG, "getAdjustTrackerToken: " + attribution);
|
||||
// Attribution: tt:r3wk5qm tn:CC-Test net:CC-Test cam: adg: cre: cl: adid:43b4d43b1f581a69e0f53fb8614f16ff ct: ca:NaN cc:
|
||||
if (null != attribution && null != attribution.trackerToken) {
|
||||
String clickLabel = null == attribution.clickLabel ? "" : attribution.clickLabel;
|
||||
String trackerName = null == attribution.trackerName ? "" : attribution.trackerName;
|
||||
String network = null == attribution.network ? "" : attribution.network;
|
||||
String trackerToken = null == attribution.trackerToken ? "" : attribution.trackerToken;
|
||||
String adjustTT = trackerToken + "@" + trackerName + "@" + network + "@" + clickLabel;
|
||||
return adjustTT;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取google adid、用户游客登录
|
||||
*/
|
||||
public void getAdidByVisitor(AppActivity nAppActivity) {
|
||||
try {
|
||||
Adjust.getGoogleAdId(nAppActivity, new OnDeviceIdsRead() {
|
||||
@Override
|
||||
public void onGoogleAdIdRead(String googleAdId) {
|
||||
String _adid = googleAdId != null ? googleAdId : Adjust.getAdid();
|
||||
_adid = _adid + "|" + Adjust.getAdid();
|
||||
Log.d(TAG, "getAdidByVisitor: " + _adid);
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_Adid, _adid == null ? "" : _adid);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust 事件 供LUA调用
|
||||
*
|
||||
* @param jsonStr eventToken,revenue,
|
||||
*/
|
||||
public void onTrackAdjustEventFun(String jsonStr) {
|
||||
try {
|
||||
Log.d(TAG, "onTrackAdjustEventFun:=>jsonStr :" + jsonStr);
|
||||
// 获取数据
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
String eventToken = json.getString("eventToken");//事件编码
|
||||
double revenue = json.getDouble("revenue");//金额
|
||||
String currency = json.getString("currency");//货币代码
|
||||
String orderId = json.getString("orderId");//剔重编码
|
||||
// 事件推送
|
||||
AdjustEvent event = new AdjustEvent(eventToken);
|
||||
// 金额大于0
|
||||
if (revenue > 0) {
|
||||
event.setRevenue(revenue, currency);
|
||||
}
|
||||
if (orderId != "") {
|
||||
event.setOrderId(orderId);
|
||||
}
|
||||
Adjust.trackEvent(event);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "onTrackAdjustEventFun:=>error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
303
android/app/src/com/cocos/game/AdsHelper.java
Normal file
@@ -0,0 +1,303 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Service;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.cocos.lib.JsbBridgeWrapper;
|
||||
import com.ddddd.one.R;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class AdsHelper {
|
||||
private static final String TAG = "AdsHelper";
|
||||
private static AdsHelper sInstance = null;
|
||||
|
||||
public static AdsHelper getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new AdsHelper();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
// JAVA
|
||||
private JsbBridgeWrapper jbw = null;
|
||||
|
||||
public JsbBridgeWrapper GetJsbBridgeWrapper() {
|
||||
if (jbw == null) {
|
||||
jbw = JsbBridgeWrapper.getInstance();
|
||||
}
|
||||
return jbw;
|
||||
}
|
||||
|
||||
public void initEventListener(AppActivity nAppActivity) {
|
||||
GetSysVersion(nAppActivity);
|
||||
GetMachineName(nAppActivity);
|
||||
GetHDID(nAppActivity);
|
||||
GetMacAddress(nAppActivity);
|
||||
GetBiosID(nAppActivity);
|
||||
GetCpuID(nAppActivity);
|
||||
GetChannel(nAppActivity);
|
||||
|
||||
SetShare(nAppActivity);
|
||||
SetShake(nAppActivity);
|
||||
SetCopy(nAppActivity);
|
||||
SetOpenUri(nAppActivity);
|
||||
}
|
||||
|
||||
//#region 基础信息获取
|
||||
public void GetSysVersion(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_AppVersion, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_AppVersion, getPackageInfo(nAppActivity).versionName);
|
||||
});
|
||||
}
|
||||
|
||||
public void GetMachineName(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_MachineName, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_MachineName, android.os.Build.MODEL);
|
||||
});
|
||||
}
|
||||
|
||||
public void GetHDID(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_HDID, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_HDID, getDeviceId(nAppActivity));
|
||||
});
|
||||
}
|
||||
|
||||
public void GetMacAddress(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_MacAddress, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_MacAddress, getLocalMacAddress(nAppActivity));
|
||||
});
|
||||
}
|
||||
|
||||
public void GetBiosID(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_BiosID, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_BiosID, getAndroidId(nAppActivity));
|
||||
});
|
||||
}
|
||||
|
||||
public void GetCpuID(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_CpuID, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_CpuID, android.os.Build.MODEL);
|
||||
});
|
||||
}
|
||||
|
||||
private PackageInfo getPackageInfo(Context context) {
|
||||
PackageInfo pi = null;
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
pi = pm.getPackageInfo(context.getPackageName(),
|
||||
PackageManager.GET_CONFIGURATIONS);
|
||||
return pi;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
private String getDeviceId(Context context) {
|
||||
String deviceId;
|
||||
//android api版本不同导致的,我们使用的28版本,没有Q,29版本有Q
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
} else {
|
||||
final TelephonyManager mTelephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
assert mTelephony != null;
|
||||
if (mTelephony.getDeviceId() != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
deviceId = mTelephony.getImei();
|
||||
} else {
|
||||
deviceId = mTelephony.getDeviceId();
|
||||
}
|
||||
} else {
|
||||
deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
}
|
||||
}
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
private String getLocalMacAddress(Context context) {
|
||||
//Android 获取本机Mac地址,需要开启wifi
|
||||
WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
WifiInfo info = wifi.getConnectionInfo();
|
||||
return info.getMacAddress();
|
||||
}
|
||||
|
||||
private String getAndroidId(Context context) {
|
||||
String ANDROID_ID = Settings.Secure.getString(context.getContentResolver(),
|
||||
Settings.Secure.ANDROID_ID);
|
||||
return ANDROID_ID;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 基础操作
|
||||
public void SetShare(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Share, arg -> {
|
||||
Log.d(TAG, "SetShare: " + arg);
|
||||
if (arg != "") {
|
||||
shareGameLink(nAppActivity, arg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SetShake(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Shake, arg -> {
|
||||
Log.d(TAG, "SetShake: " + arg);
|
||||
try {
|
||||
Vibrator vib = (Vibrator) nAppActivity.getSystemService(Service.VIBRATOR_SERVICE);
|
||||
boolean b = vib.hasVibrator();
|
||||
if (b) {
|
||||
//当前设备有振动器
|
||||
vib.vibrate(new long[]{300, 500}, -1);
|
||||
} else {
|
||||
//当前设备没有振动器
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void SetCopy(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Copy, arg -> {
|
||||
Log.d(TAG, "SetCopy: " + arg);
|
||||
if (arg != "") {
|
||||
nAppActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ClipboardManager cm = (ClipboardManager) AppActivity.nAppActivity
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
// 创建普通字符型ClipData
|
||||
ClipData mClipData = ClipData.newPlainText("Label", arg);
|
||||
// 将ClipData内容放到系统剪贴板里。
|
||||
cm.setPrimaryClip(mClipData);
|
||||
//已复制到剪贴板
|
||||
Toast.makeText(AppActivity.nAppActivity, "Kopyalandı",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SetOpenUri(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Open, arg -> {
|
||||
Log.d(TAG, "SetOpenUri: " + arg);
|
||||
try {
|
||||
Intent mIntent = new Intent(Intent.ACTION_VIEW);
|
||||
mIntent.setData(Uri.parse(arg));
|
||||
nAppActivity.startActivity(mIntent);
|
||||
} catch (Exception e) {
|
||||
// 防止crash (如果手机上没有安装处理某个scheme开头的url的APP,
|
||||
// 会导致crash)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void shareGameLink(AppActivity nAppActivity, String jsonStr) {
|
||||
try {
|
||||
JSONObject jo = new JSONObject(jsonStr);
|
||||
String title = jo.getString("title");
|
||||
String text = jo.getString("text");
|
||||
String sendType = jo.getString("type");
|
||||
String filter = jo.getString("filter");
|
||||
String[] filterArr = filter.split("\\|");
|
||||
//for (int i = 0; i < filterArr.length; i++) {
|
||||
// Log.i("FILTER:::: ", filterArr[i]);
|
||||
//}
|
||||
|
||||
Resources r = nAppActivity.getApplicationContext().getResources();
|
||||
Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
|
||||
+ r.getResourcePackageName(R.mipmap.ic_launcher) + "/"
|
||||
+ r.getResourceTypeName(R.mipmap.ic_launcher) + "/"
|
||||
+ r.getResourceEntryName(R.mipmap.ic_launcher));
|
||||
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.setType(sendType);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
|
||||
//sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
|
||||
PackageManager pm = nAppActivity.getPackageManager();
|
||||
List<ResolveInfo> activityList = pm.queryIntentActivities(sendIntent, 0);
|
||||
List<Intent> shareIntents = new ArrayList<Intent>();
|
||||
|
||||
HashMap hashMap = new HashMap();
|
||||
for (ResolveInfo info : activityList) {
|
||||
String packageName = info.activityInfo.packageName;
|
||||
if (!hashMap.containsKey(packageName) && isFilterPackageName(packageName, filterArr)) {
|
||||
Intent targeted = new Intent(Intent.ACTION_SEND);
|
||||
if (packageName.contains("facebook")) {
|
||||
targeted.setType("text/plain");
|
||||
} else {
|
||||
targeted.setType(sendType);
|
||||
}
|
||||
targeted.setPackage(packageName);
|
||||
targeted.putExtra(Intent.EXTRA_TEXT, text);
|
||||
//targeted.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
shareIntents.add(targeted);
|
||||
Log.i("__ADD:::: ", packageName);
|
||||
hashMap.put(packageName, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (shareIntents.size() > 0) {
|
||||
Intent chooserIntent = Intent.createChooser(shareIntents.remove(0), title);
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, shareIntents.toArray(new Intent[0]));
|
||||
//getInstance().startActivity(chooserIntent);
|
||||
nAppActivity.startActivityForResult(chooserIntent, nAppActivity.REQUEST_CODE_SHARE_GAME_LINK);
|
||||
} else {
|
||||
nAppActivity.startActivityForResult(sendIntent, nAppActivity.REQUEST_CODE_SHARE_GAME_LINK);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFilterPackageName(String sname, String[] filterArr) {
|
||||
for (int i = 0; i < filterArr.length; i++) {
|
||||
if (sname.contains(filterArr[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 获取渠道编号
|
||||
public void GetChannel(AppActivity nAppActivity) {
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Channel, arg -> {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_Channel, "liuhaotest");
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -1,44 +1,217 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2015-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
Copyright (c) 2015-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package com.cocos.game;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.cocos.lib.JsbBridgeWrapper;
|
||||
import com.cocos.service.SDKWrapper;
|
||||
import com.cocos.lib.CocosActivity;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
|
||||
import com.google.android.gms.common.Scopes;
|
||||
import com.google.android.gms.common.api.Scope;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.luck.picture.lib.basic.PictureSelector;
|
||||
import com.luck.picture.lib.config.SelectMimeType;
|
||||
import com.luck.picture.lib.config.SelectModeConfig;
|
||||
import com.luck.picture.lib.entity.LocalMedia;
|
||||
import com.luck.picture.lib.interfaces.OnResultCallbackListener;
|
||||
import com.luck.picture.lib.language.LanguageConfig;
|
||||
import com.ddddd.one.R;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
import com.cocos.game.PermissionsUtil.IPermissionsCallback;
|
||||
|
||||
public class AppActivity extends CocosActivity {
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AppActivity extends CocosActivity implements
|
||||
IPermissionsCallback {
|
||||
|
||||
public static final int REQUEST_CODE_SHARE_GAME_LINK = 1001; //游戏分享
|
||||
public static final int REQUEST_CODE_GOOGLE_LOGIN = 9001; //Google登录
|
||||
public static final int REQUEST_CODE_GOOGLE_PAY_SERVICES = 10001; //Google支付服务
|
||||
|
||||
//动态权限
|
||||
private static final int MY_PERMISSIONS_REQUEST_CAMERA = 0; // 相机相册
|
||||
private static final int MY_PERMISSIONS_REQUEST_StART = 1; // 启动游戏
|
||||
private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 3;//语音
|
||||
|
||||
private static final String TAG = "AppActivity";
|
||||
private GoogleSignInClient mGoogleSignInClient;
|
||||
private JsbBridgeWrapper jbw = null;
|
||||
ShakeDetector mShaker;
|
||||
static SharedPreferences sharedPreferences;
|
||||
public static int selectImageIndex = 0;
|
||||
public static PermissionsUtil permissionsUtil;
|
||||
|
||||
private static CocosActivity sContext = null;
|
||||
public static AppActivity nAppActivity = null;
|
||||
|
||||
public AppActivity() {
|
||||
nAppActivity = this;
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
return sContext;
|
||||
}
|
||||
|
||||
private static ImageView sSplashBgImageView = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// DO OTHER INITIALIZATION BELOW
|
||||
SDKWrapper.shared().init(this);
|
||||
sContext = this;
|
||||
|
||||
if (jbw == null)
|
||||
jbw = JsbBridgeWrapper.getInstance();
|
||||
|
||||
jbw.addScriptEventListener(EventNameUtil.Android_CloseSplash, arg -> {
|
||||
if (sSplashBgImageView != null) {
|
||||
Log.d(TAG, "onCreate: " + EventNameUtil.Android_CloseSplash);
|
||||
hideSplash();
|
||||
}
|
||||
});
|
||||
showSplash();
|
||||
|
||||
CrashReport.initCrashReport(getApplicationContext());
|
||||
sharedPreferences = getSharedPreferences("path", MODE_PRIVATE);
|
||||
|
||||
// 初始化 RtcEngine,并加入频道。
|
||||
ZegoUtil.getInstance().zegoInitializeEngine(nAppActivity, getApplicationContext());
|
||||
|
||||
// google play game service sign
|
||||
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
|
||||
//.requestScopes(new Scope(Scopes.PROFILE))
|
||||
.requestScopes(new Scope(Scopes.PROFILE))
|
||||
.requestServerAuthCode(getString(R.string.google_client_id))
|
||||
.requestEmail()
|
||||
.build();
|
||||
// GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
||||
// .requestIdToken(getString(R.string.google_client_id))
|
||||
// .requestEmail()
|
||||
// .build();
|
||||
// Build a GoogleSignInClient with the options specified by gso.
|
||||
mGoogleSignInClient = GoogleSignIn.getClient(nAppActivity, gso);
|
||||
|
||||
GoogleUtil.getInstance().InitLogin(nAppActivity, getApplicationContext(), mGoogleSignInClient);
|
||||
GoogleUtil.getInstance().InitLoginOut(nAppActivity, getApplicationContext(), mGoogleSignInClient);
|
||||
GoogleUtil.getInstance().initGooglePay(nAppActivity, getApplicationContext());
|
||||
|
||||
|
||||
//游客账号
|
||||
jbw.addScriptEventListener(EventNameUtil.Android_Adid, arg -> {
|
||||
AdjustUtil.getInstance().getAdidByVisitor(nAppActivity);
|
||||
});
|
||||
//adjust归因
|
||||
jbw.addScriptEventListener(EventNameUtil.Android_AdjustTT, arg -> {
|
||||
final String adjustTT = AdjustUtil.getInstance().getAdjustTrackerToken();
|
||||
EventToScriptUtil.getInstance().actCallBack(nAppActivity, adjustTT);
|
||||
});
|
||||
//adjust发送事件
|
||||
jbw.addScriptEventListener(EventNameUtil.Android_AdjustSend, arg -> {
|
||||
AdjustUtil.getInstance().onTrackAdjustEventFun(arg);
|
||||
});
|
||||
|
||||
//图片上传
|
||||
jbw.addScriptEventListener(EventNameUtil.Android_FeedImage, arg -> {
|
||||
Log.d(TAG, "onCreate: Android_FeedImage");
|
||||
selectImageIndex = 1;
|
||||
Message msg = new Message();
|
||||
msg.what = HANDLER_IMAGE_CHOOSE;
|
||||
msg.obj = "";
|
||||
handler.sendMessage(msg);
|
||||
});
|
||||
jbw.addScriptEventListener(EventNameUtil.Android_HeadImage, arg -> {
|
||||
Log.d(TAG, "onCreate: Android_HeadImage");
|
||||
selectImageIndex = 0;
|
||||
Message msg = new Message();
|
||||
msg.what = HANDLER_IMAGE_CHOOSE;
|
||||
msg.obj = "";
|
||||
handler.sendMessage(msg);
|
||||
});
|
||||
|
||||
//基础信息
|
||||
AdsHelper.getInstance().initEventListener(nAppActivity);
|
||||
try {
|
||||
mShaker = new ShakeDetector(this);
|
||||
mShaker.registerOnShakeListener(new ShakeDetector.OnShakeListener() {
|
||||
@Override
|
||||
public void onShake() {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d("shake2", "shake2: " + "shake2");
|
||||
}
|
||||
});
|
||||
mShaker.start();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 防止屏幕休眠
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
SDKWrapper.shared().onActivityResult(requestCode, resultCode, data);
|
||||
Log.d(TAG, "onActivityResult: " + requestCode);
|
||||
if (requestCode == REQUEST_CODE_SHARE_GAME_LINK) {
|
||||
EventToScriptUtil.getInstance().setToScript(nAppActivity, EventNameUtil.Android_Share, resultCode + "");
|
||||
} else if (requestCode == REQUEST_CODE_GOOGLE_LOGIN) {
|
||||
Log.d(TAG, "onActivityResult: " + requestCode);
|
||||
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
|
||||
GoogleUtil.getInstance().HandleSignInResult(nAppActivity, getApplicationContext(), task);
|
||||
} else if (requestCode == REQUEST_CODE_GOOGLE_PAY_SERVICES) {
|
||||
// The Task returned from this call is always completed, no need to attach
|
||||
// a listener.
|
||||
Log.d(TAG, "onActivityResult: REQUEST_CODE_GOOGLE_PAY_SERVICES");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,13 +233,10 @@ public class AppActivity extends CocosActivity {
|
||||
if (!isTaskRoot()) {
|
||||
return;
|
||||
}
|
||||
SDKWrapper.shared().onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
SDKWrapper.shared().onActivityResult(requestCode, resultCode, data);
|
||||
SDKWrapper.shared().onDestroy();
|
||||
mShaker.stop();
|
||||
ZegoUtil.getInstance().zegoDestroyEngine();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,4 +292,253 @@ public class AppActivity extends CocosActivity {
|
||||
SDKWrapper.shared().onLowMemory();
|
||||
super.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
//应用第一次安装,并且权限被禁用时,返回true
|
||||
//权限被禁用时,返回true
|
||||
//权限被禁用且不再提示时,返回false
|
||||
//已授权时返回false
|
||||
int mRequestPermissionCount = sharedPreferences.getInt(requestCode + "", 0);
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
|
||||
mRequestPermissionCount = mRequestPermissionCount + 1;
|
||||
//// Should we show an explanation?
|
||||
//// 1.第一次拒绝后提示用户为何需要此类权限、做第二次授权请求
|
||||
//if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[0])) {
|
||||
// //Show permission explanation dialog...
|
||||
// permissionsUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
//} else {
|
||||
// // 用户已经选择:禁用且不再提示、此时一般不需要再次提示授权说明
|
||||
// //Never ask again selected, or device policy prohibits the app from having that permission.
|
||||
// //So, disable that feature, or fall back to another situation...
|
||||
// permissionsUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
//}
|
||||
// permissionsUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
} else {
|
||||
mRequestPermissionCount = 0;
|
||||
}
|
||||
sharedPreferences.edit().putInt(requestCode + "", mRequestPermissionCount).apply();
|
||||
if (requestCode == MY_PERMISSIONS_REQUEST_RECORD_AUDIO && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d(TAG, "onRequestPermissionsResult:joinChannel " + requestCode);
|
||||
ZegoUtil.getInstance().zegoLoginFun(nAppActivity, getContext(), ZegoUtil.ZegoJoinJsonStr);
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////////
|
||||
// 动态权限获取结果回调
|
||||
// ///////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void onPermissionsGranted(int requestCode, String... permission) {
|
||||
Log.d("cocos1", "onPermissionsGranted joinChannel " + requestCode);
|
||||
// 权限获取回调
|
||||
switch (requestCode) {
|
||||
case MY_PERMISSIONS_REQUEST_CAMERA: // 打开相机相册
|
||||
ChooseImageDialog();
|
||||
break;
|
||||
case MY_PERMISSIONS_REQUEST_StART: // 启动游戏
|
||||
break;
|
||||
case MY_PERMISSIONS_REQUEST_RECORD_AUDIO://打开语音
|
||||
ZegoUtil.getInstance().zegoLoginFun(nAppActivity, getContext(), ZegoUtil.ZegoJoinJsonStr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsDenied(int requestCode, String... permission) {
|
||||
// 权限被拒绝回调
|
||||
switch (requestCode) {
|
||||
case MY_PERMISSIONS_REQUEST_CAMERA:// 打开相机相册
|
||||
|
||||
break;
|
||||
case MY_PERMISSIONS_REQUEST_StART:// 启动游戏
|
||||
nAppActivity.finish();
|
||||
System.exit(0);
|
||||
break;
|
||||
case MY_PERMISSIONS_REQUEST_RECORD_AUDIO://打开语音
|
||||
Log.d(TAG, "onPermissionsDenied: " + "1");
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_Login, "1");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static final int HANDLER_IMAGE_CHOOSE = 1;
|
||||
public static final int HANDLER_ZEGOLOGIN = 3;//加入频道
|
||||
|
||||
public static Handler handler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case HANDLER_IMAGE_CHOOSE:
|
||||
ChooseImageDialog();
|
||||
break;
|
||||
case HANDLER_ZEGOLOGIN: {
|
||||
// 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
permissionsUtil = PermissionsUtil
|
||||
.with(nAppActivity)
|
||||
.requestCode(MY_PERMISSIONS_REQUEST_RECORD_AUDIO)
|
||||
.isDebug(true)
|
||||
.requestPermissionCount(sharedPreferences.getInt(MY_PERMISSIONS_REQUEST_RECORD_AUDIO + "", 0))
|
||||
// 开启log
|
||||
.permissions(
|
||||
PermissionsUtil.Permission.Microphone.RECORD_AUDIO)
|
||||
.request();
|
||||
} else {
|
||||
String strParam = (String) msg.obj;
|
||||
ZegoUtil.getInstance().zegoLoginFun(nAppActivity, getContext(), strParam);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 弹出选择图片的选择框 android选择图片
|
||||
*/
|
||||
public static void ChooseImageDialog() {
|
||||
int languageConfig = LanguageConfig.ENGLISH;
|
||||
Locale _locale = Locale.getDefault();
|
||||
Log.i(TAG, "onCancel: "+_locale);
|
||||
if (_locale.equals(Locale.ENGLISH)
|
||||
// || _locale.equals(Locale.CHINESE)
|
||||
// || _locale.equals(Locale.SIMPLIFIED_CHINESE)
|
||||
// || _locale.equals(Locale.TRADITIONAL_CHINESE)
|
||||
|| _locale.equals(Locale.KOREA)
|
||||
|| _locale.equals(Locale.GERMANY)
|
||||
|| _locale.equals(Locale.FRANCE)
|
||||
|| _locale.equals(Locale.JAPAN)
|
||||
|| _locale.equals(new Locale("vi"))
|
||||
|| _locale.equals(new Locale("es", "ES"))
|
||||
|| _locale.equals(new Locale("pt", "PT"))
|
||||
|| _locale.equals(new Locale("ar", "AE"))
|
||||
|| _locale.equals(new Locale("ru", "rRU"))
|
||||
|| _locale.equals(new Locale("cs", "rCZ"))
|
||||
|| _locale.equals(new Locale("kk", "rKZ"))
|
||||
) {
|
||||
languageConfig = LanguageConfig.SYSTEM_LANGUAGE;
|
||||
}
|
||||
if (_locale.equals(Locale.CHINESE)
|
||||
|| _locale.equals(Locale.SIMPLIFIED_CHINESE)
|
||||
|| _locale.equals(Locale.TRADITIONAL_CHINESE)) {
|
||||
languageConfig = LanguageConfig.ENGLISH;
|
||||
}
|
||||
if (selectImageIndex == 0) {
|
||||
PictureSelector.create(nAppActivity)
|
||||
.openGallery(SelectMimeType.ofImage())
|
||||
.setImageEngine(GlideEngine.createGlideEngine())//设置相册图片加载引擎
|
||||
.setSelectionMode(SelectModeConfig.SINGLE)//单选或是多选
|
||||
.setCompressEngine(new PictureSelectlucksiege.ImageFileCompressEngine())//设置相册压缩引擎
|
||||
.setCropEngine(new PictureSelectlucksiege.ImageFileCropEngine())//设置相册裁剪引擎
|
||||
//.setCameraInterceptListener(new PictureSelectlucksiege.MeOnCameraInterceptListener())//自定义拍照
|
||||
//.setPermissionDescriptionListener(new PictureSelectlucksiege.MeOnPermissionDescriptionListener())
|
||||
.setPermissionDeniedListener(new PictureSelectlucksiege.MeOnPermissionDeniedListener())
|
||||
.setLanguage(languageConfig)
|
||||
.setDefaultLanguage(languageConfig)
|
||||
.forResult(new OnResultCallbackListener<LocalMedia>() {
|
||||
@Override
|
||||
public void onResult(ArrayList<LocalMedia> result) {
|
||||
if (result != null && result.size() > 0) {
|
||||
Log.i(TAG, "onResult: " + result.get(0).getAvailablePath());
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Android_HeadImage, result.get(0).getAvailablePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Log.i(TAG, "onCancel: ");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
PictureSelector.create(nAppActivity)
|
||||
.openGallery(SelectMimeType.ofImage())
|
||||
.setImageEngine(GlideEngine.createGlideEngine())//设置相册图片加载引擎
|
||||
.setSelectionMode(SelectModeConfig.SINGLE)//单选或是多选
|
||||
.setCompressEngine(new PictureSelectlucksiege.ImageFileCompressEngine())//设置相册压缩引擎
|
||||
.setCropEngine(new PictureSelectlucksiege.ImageFileCropEngine())//设置相册裁剪引擎
|
||||
.setCameraInterceptListener(new PictureSelectlucksiege.MeOnCameraInterceptListener())//自定义拍照
|
||||
//.setPermissionDescriptionListener(new PictureSelectlucksiege.MeOnPermissionDescriptionListener())
|
||||
.setPermissionDeniedListener(new PictureSelectlucksiege.MeOnPermissionDeniedListener())
|
||||
.setLanguage(languageConfig)
|
||||
.setDefaultLanguage(languageConfig)
|
||||
.forResult(new OnResultCallbackListener<LocalMedia>() {
|
||||
@Override
|
||||
public void onResult(ArrayList<LocalMedia> result) {
|
||||
if (result != null && result.size() > 0) {
|
||||
Log.i(TAG, "onResult: " + result.get(0).getAvailablePath());
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Android_FeedImage, result.get(0).getAvailablePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Log.i(TAG, "onCancel: ");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 供 JS 通过 jsb.reflection 调用的 Adjust 事件上报方法
|
||||
*/
|
||||
public static void trackAdjustEvent(String eventToken) {
|
||||
try {
|
||||
com.adjust.sdk.AdjustEvent event = new com.adjust.sdk.AdjustEvent(eventToken);
|
||||
com.adjust.sdk.Adjust.trackEvent(event);
|
||||
Log.d(TAG, "trackAdjustEvent: " + eventToken);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开屏背景
|
||||
*/
|
||||
private static void showSplash() {
|
||||
sSplashBgImageView = new ImageView(sContext);
|
||||
// sSplashBgImageView.setBackgroundColor(
|
||||
// // sContext.getResources().getColor(R.color.splashBg)
|
||||
// sContext.getResources().getColor(R.color.viewfinder_laser, null)
|
||||
//);
|
||||
//全屏背景图
|
||||
sSplashBgImageView.setImageResource(R.drawable.splash);
|
||||
//logo居中、其他区域颜色覆盖
|
||||
//sSplashBgImageView.setImageResource(R.drawable.splash_slogan_with_bg);
|
||||
//sSplashBgImageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||
sContext.addContentView(sSplashBgImageView,
|
||||
new WindowManager.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 这是给 CC JS 调用的隐藏原生开屏背景的方法
|
||||
*/
|
||||
public static void hideSplash() {
|
||||
sContext.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (sSplashBgImageView != null) {
|
||||
// sSplashBgImageView.setVisibility(View.GONE);
|
||||
sSplashBgImageView.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(1000)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
sSplashBgImageView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
39
android/app/src/com/cocos/game/EventNameUtil.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.cocos.game;
|
||||
|
||||
|
||||
public class EventNameUtil {
|
||||
public static final String Android_AppVersion = "Native_AppVersion";
|
||||
public static final String Android_MachineName = "Native_MachineName";
|
||||
public static final String Android_MacAddress = "Native_MacAddress";
|
||||
public static final String Android_HDID = "Native_HDID";
|
||||
public static final String Android_BiosID = "Native_BiosID";
|
||||
public static final String Android_CpuID = "Native_CpuID";
|
||||
public static final String Android_Channel = "Native_Channel";
|
||||
|
||||
public static final String Android_CloseSplash = "Native_CloseSplash";
|
||||
|
||||
public static final String Android_Share = "Native_Share";
|
||||
public static final String Android_Copy = "Native_Copy";
|
||||
public static final String Android_Open = "Native_Open";
|
||||
public static final String Android_Shake = "Native_Shake";
|
||||
|
||||
public static final String Android_Adid = "Native_Adid";
|
||||
public static final String Android_AdjustTT = "Native_AdjustTT";
|
||||
public static final String Android_AdjustSend = "Native_AdjustSend";
|
||||
|
||||
public static final String Android_FeedImage = "Native_FeedImage";//反馈图片
|
||||
public static final String Android_HeadImage = "Native_HeadImage";//头像图片
|
||||
|
||||
public static final String Android_Login = "Native_GoogleLogin";
|
||||
public static final String Android_LoginOut = "Native_GoogleLoginOut";
|
||||
public static final String Android_Pay = "Native_GooglePay";
|
||||
|
||||
public static final String Zg_Login = "Native_ZgLogin";
|
||||
public static final String Zg_LoginOut = "Native_ZgLoginOut";
|
||||
public static final String Zg_StopPlay = "Native_ZgStopPlay";
|
||||
public static final String Zg_StartPlay = "Native_ZgStartPlay";
|
||||
public static final String Zg_StopPublish = "Native_ZgStopPublish";
|
||||
public static final String Zg_StartPublish = "Native_ZgStartPublish";
|
||||
public static final String Zg_AllPlay = "Native_ZgAllPlay";
|
||||
public static final String Zg_AudioVolume = "Native_ZgAudioVolume";
|
||||
}
|
||||
69
android/app/src/com/cocos/game/EventToScriptUtil.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.cocos.lib.JsbBridgeWrapper;
|
||||
|
||||
public class EventToScriptUtil {
|
||||
|
||||
private static final String TAG = "EventToScriptUtil";
|
||||
private static EventToScriptUtil _instance = null;
|
||||
|
||||
public static EventToScriptUtil getInstance() {
|
||||
if (_instance == null) {
|
||||
_instance = new EventToScriptUtil();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private AppActivity curAppActivity = null;
|
||||
private String adjustTT = "";
|
||||
private JsbBridgeWrapper jbw = null;
|
||||
|
||||
public void actCallBack(AppActivity nAppActivity, String _adjustTT) {
|
||||
Log.i(TAG, "actCallBack: " + _adjustTT);
|
||||
if (this.curAppActivity == null)
|
||||
this.curAppActivity = nAppActivity;
|
||||
if (_adjustTT != "") {
|
||||
this.callBackToLua(_adjustTT);
|
||||
} else if (this.adjustTT != "") {
|
||||
this.callBackToLua(this.adjustTT);
|
||||
}
|
||||
}
|
||||
|
||||
public void appCallBack(String _adjustTT) {
|
||||
Log.i(TAG, "appCallBack: " + _adjustTT);
|
||||
if (_adjustTT != "" && this.curAppActivity != null) {
|
||||
this.adjustTT = _adjustTT;
|
||||
this.callBackToLua(_adjustTT);
|
||||
}
|
||||
}
|
||||
|
||||
public void setToScript(AppActivity nAppActivity, String _eventName, String _val) {
|
||||
if (this.curAppActivity == null)
|
||||
this.curAppActivity = nAppActivity;
|
||||
|
||||
Log.d(TAG, "setToScript: " + _eventName + " " + _val);
|
||||
dispatchEventToScript(_eventName, _val);
|
||||
}
|
||||
|
||||
private void callBackToLua(final String adjustTT) {
|
||||
dispatchEventToScript(EventNameUtil.Android_AdjustTT, adjustTT);
|
||||
}
|
||||
|
||||
|
||||
public void dispatchEventToScript(final String _eventName, final String _val) {
|
||||
// if (this.curAppActivity == null) {
|
||||
// return;
|
||||
// }
|
||||
try {
|
||||
if (jbw == null) {
|
||||
jbw = JsbBridgeWrapper.getInstance();
|
||||
}
|
||||
jbw.dispatchEventToScript(_eventName, _val);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
113
android/app/src/com/cocos/game/GlideEngine.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.luck.picture.lib.engine.ImageEngine;
|
||||
import com.luck.picture.lib.utils.ActivityCompatHelper;
|
||||
|
||||
import com.ddddd.one.R;
|
||||
|
||||
public class GlideEngine implements ImageEngine {
|
||||
|
||||
/**
|
||||
* 加载图片
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param url 资源url
|
||||
* @param imageView 图片承载控件
|
||||
*/
|
||||
@Override
|
||||
public void loadImage(Context context, String url, ImageView imageView) {
|
||||
if (!ActivityCompatHelper.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context)
|
||||
.load(url)
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) {
|
||||
if (!ActivityCompatHelper.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context)
|
||||
.load(url)
|
||||
.override(maxWidth, maxHeight)
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载相册目录封面
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param url 图片路径
|
||||
* @param imageView 承载图片ImageView
|
||||
*/
|
||||
@Override
|
||||
public void loadAlbumCover(Context context, String url, ImageView imageView) {
|
||||
if (!ActivityCompatHelper.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.override(180, 180)
|
||||
.sizeMultiplier(0.5f)
|
||||
.transform(new CenterCrop(), new RoundedCorners(8))
|
||||
.placeholder(R.drawable.ps_image_placeholder)
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加载图片列表图片
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param url 图片路径
|
||||
* @param imageView 承载图片ImageView
|
||||
*/
|
||||
@Override
|
||||
public void loadGridImage(Context context, String url, ImageView imageView) {
|
||||
if (!ActivityCompatHelper.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context)
|
||||
.load(url)
|
||||
.override(200, 200)
|
||||
.centerCrop()
|
||||
.placeholder(R.drawable.ps_image_placeholder)
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseRequests(Context context) {
|
||||
if (!ActivityCompatHelper.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context).pauseRequests();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeRequests(Context context) {
|
||||
if (!ActivityCompatHelper.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context).resumeRequests();
|
||||
}
|
||||
|
||||
private GlideEngine() {
|
||||
}
|
||||
|
||||
private static final class InstanceHolder {
|
||||
static final GlideEngine instance = new GlideEngine();
|
||||
}
|
||||
|
||||
public static GlideEngine createGlideEngine() {
|
||||
return InstanceHolder.instance;
|
||||
}
|
||||
}
|
||||
855
android/app/src/com/cocos/game/GoogleUtil.java
Normal file
@@ -0,0 +1,855 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.adjust.sdk.Adjust;
|
||||
import com.adjust.sdk.OnDeviceIdsRead;
|
||||
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.ConsumeParams;
|
||||
import com.android.billingclient.api.ConsumeResponseListener;
|
||||
import com.android.billingclient.api.ProductDetails;
|
||||
import com.android.billingclient.api.ProductDetailsResponseListener;
|
||||
import com.android.billingclient.api.Purchase;
|
||||
import com.android.billingclient.api.PurchasesResponseListener;
|
||||
import com.android.billingclient.api.PurchasesUpdatedListener;
|
||||
import com.android.billingclient.api.QueryProductDetailsParams;
|
||||
import com.android.billingclient.api.QueryPurchasesParams;
|
||||
import com.android.billingclient.api.SkuDetails;
|
||||
import com.android.billingclient.api.SkuDetailsParams;
|
||||
import com.android.billingclient.api.SkuDetailsResponseListener;
|
||||
import com.cocos.lib.JsbBridgeWrapper;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.android.gms.common.api.ApiException;
|
||||
import com.google.android.gms.games.Games;
|
||||
import com.google.android.gms.games.Player;
|
||||
import com.google.android.gms.games.PlayersClient;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GoogleUtil {
|
||||
|
||||
private static final String TAG = "GoogleUtil";
|
||||
private static GoogleUtil sInstance = null;
|
||||
/**
|
||||
* 缓存的SKU列表
|
||||
*/
|
||||
private static Map<String, SkuDetails> skuDetailsMap = new HashMap<>();
|
||||
private static Map<String, ProductDetails> productDetailsMap = new HashMap<>();
|
||||
private static PurchasesUpdatedListener purchasesUpdatedListener;
|
||||
private static BillingClient billingClient;
|
||||
|
||||
public static GoogleUtil getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new GoogleUtil();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
// JAVA
|
||||
private JsbBridgeWrapper jbw = null;
|
||||
|
||||
public JsbBridgeWrapper GetJsbBridgeWrapper() {
|
||||
if (jbw == null) {
|
||||
jbw = JsbBridgeWrapper.getInstance();
|
||||
}
|
||||
return jbw;
|
||||
}
|
||||
|
||||
private static Context mContext;
|
||||
private static AppActivity mActivity;
|
||||
|
||||
/**
|
||||
* 初始化信息
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private static void InitInfo(AppActivity activity, Context _context) {
|
||||
if (mActivity == null)
|
||||
mActivity = activity;
|
||||
if (mContext == null)
|
||||
mContext = _context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Google登录信息
|
||||
*
|
||||
* @param nAppActivity
|
||||
* @param _context
|
||||
* @param mGoogleSignInClient
|
||||
*/
|
||||
public void InitLogin(AppActivity nAppActivity, Context _context, GoogleSignInClient mGoogleSignInClient) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Login, arg -> {
|
||||
Log.d(TAG, "InitLogin: " + arg);
|
||||
// 判断Google服务是否可用
|
||||
if (!IsGooglePlayServices()) {
|
||||
GoogleLoginSuccess(-3, null);
|
||||
return;
|
||||
}
|
||||
// 检查现有的登录用户
|
||||
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(mContext);//getApplicationContext()
|
||||
if (null != account && account.getServerAuthCode() != null) {
|
||||
//未登录
|
||||
GoogleLoginSuccess(1, account);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
//设置回调时requestCode
|
||||
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
|
||||
mActivity.startActivityForResult(signInIntent, nAppActivity.REQUEST_CODE_GOOGLE_LOGIN);
|
||||
} catch (Exception e) {
|
||||
GoogleLoginSuccess(-2, null);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Google登出信息
|
||||
*
|
||||
* @param nAppActivity
|
||||
* @param _context
|
||||
* @param mGoogleSignInClient
|
||||
*/
|
||||
public void InitLoginOut(AppActivity nAppActivity, Context _context, GoogleSignInClient mGoogleSignInClient) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_LoginOut, arg -> {
|
||||
Log.d(TAG, "InitLogin: " + arg);
|
||||
// 判断Google服务是否可用
|
||||
if (!IsGooglePlayServicesNoShow()) {
|
||||
Log.d(TAG, "InitLoginOut: IsGooglePlayServicesNoShow");
|
||||
return;
|
||||
}
|
||||
// 检查现有的登录用户
|
||||
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(mContext);
|
||||
if (null != account && account.getServerAuthCode() != null) {
|
||||
mGoogleSignInClient.signOut().addOnCompleteListener(mActivity,
|
||||
new OnCompleteListener<Void>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
// at this point, the user is signed out.
|
||||
Log.d(TAG, "onComplete:signOut ");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化google支付
|
||||
*/
|
||||
public void initGooglePay(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Android_Pay, strParam -> {
|
||||
try {
|
||||
JSONObject jo = new JSONObject(strParam);
|
||||
final String sku_id = jo.getString("sku_id");
|
||||
final String order_Id = jo.getString("order_Id");
|
||||
final int pay_Type = jo.getInt("pay_Type");
|
||||
final String o_uid = jo.getString("uid");
|
||||
|
||||
CrashReport.setUserId(o_uid);// Bugly 设置用户ID
|
||||
|
||||
// 判断Google服务是否可用
|
||||
if (!IsGooglePlayServicesNoShow()) {
|
||||
if (pay_Type == 1) {
|
||||
googlePaySuccess(-3, "", sku_id, "", pay_Type);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 初始化(监听支付事件)
|
||||
if (billingClient == null) {
|
||||
purchasesUpdatedListener = new PurchasesUpdatedListener() {
|
||||
@Override
|
||||
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
|
||||
onPurchasesUpdatedFun(billingResult, purchases, sku_id, pay_Type);
|
||||
}
|
||||
};
|
||||
billingClient = BillingClient.newBuilder(nAppActivity)
|
||||
.setListener(purchasesUpdatedListener)
|
||||
.enablePendingPurchases()
|
||||
.build();
|
||||
}
|
||||
if (billingClient != null) {
|
||||
// 连接Google服务器(必须)
|
||||
if (!billingClient.isReady()) {
|
||||
Log.d(TAG, "BillingClient: Start connection...");
|
||||
billingClient.startConnection(new BillingClientStateListener() {
|
||||
@Override
|
||||
public void onBillingSetupFinished(BillingResult billingResult) {
|
||||
if (billingResult != null) {
|
||||
Log.d(TAG, "BillingClient: Start connection..." + billingResult.getResponseCode());
|
||||
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
|
||||
// The BillingClient is ready. You can query purchases here.
|
||||
if (pay_Type == 1) {
|
||||
// 判断Google服务是否支持ProductDetails服务支付
|
||||
if (IsUseProductDetails())
|
||||
getGoogleProductDetail(sku_id, order_Id, pay_Type, o_uid);
|
||||
else
|
||||
getGoogleSkuDetail(sku_id, order_Id, pay_Type, o_uid);
|
||||
} else {
|
||||
if (IsUseProductDetails())
|
||||
queryProductGoogleHistoryOrder();
|
||||
else
|
||||
queryGoogleHistoryOrder();
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "onBillingSetupFinished--error==" + billingResult.getDebugMessage() + "====" + billingResult.getResponseCode());
|
||||
googlePaySuccess(-3, "", sku_id, "", pay_Type);
|
||||
// Toast.makeText(nAppActivity, "Bu cihaz desteklenmiyor", Toast.LENGTH_SHORT).show();//不支持此设备
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "onBillingSetupFinished: billingResult ==== null");
|
||||
googlePaySuccess(-3, "", sku_id, "", pay_Type);
|
||||
// Toast.makeText(nAppActivity, "Bu cihaz desteklenmiyor", Toast.LENGTH_SHORT).show();//不支持此设备
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBillingServiceDisconnected() {
|
||||
Log.d(TAG, "onBillingServiceDisconnected");
|
||||
// Try to restart the connection on the next request to
|
||||
// Google Play by calling the startConnection() method.
|
||||
//if(billingClient != null)
|
||||
// billingClient.startConnection(this);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (pay_Type == 1) {
|
||||
if (IsUseProductDetails())
|
||||
getGoogleProductDetail(sku_id, order_Id, pay_Type, o_uid);
|
||||
else
|
||||
getGoogleSkuDetail(sku_id, order_Id, pay_Type, o_uid);
|
||||
} else {
|
||||
if (IsUseProductDetails())
|
||||
queryProductGoogleHistoryOrder();
|
||||
else
|
||||
queryGoogleHistoryOrder();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "initGooglePay=>json_error " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param purchase
|
||||
*/
|
||||
public void handlePurchase(Purchase purchase) {
|
||||
// Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
|
||||
|
||||
// Verify the purchase.
|
||||
// Ensure entitlement was not already granted for this purchaseToken.
|
||||
// Grant entitlement to the user.
|
||||
// 已支付状态处理
|
||||
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
|
||||
String sku_id = purchase.getSkus().get(0);
|
||||
String packageName = purchase.getPackageName();
|
||||
// {"orderId":"GPA.3328-7219-1739-02590","packageName":"com.cxhdgame.kxddz","productId":"cx101_1","purchaseTime":1636445521030,"purchaseState":0,"purchaseToken":"edmllomemkamjnhijmiainna.AO-J1OyyWeKcqednsYd1xS3hCTj1dPU2VmClddFHAwu5k8tI2a3uUYSmwyl7syqweO1aNRri3eSno94iBSE_kiKlktdk_pYbQg","quantity":1,"acknowledged":false}
|
||||
Log.d(TAG, "handlePurchase: packageName:" + sku_id);
|
||||
Log.d(TAG, "handlePurchase: productId:" + packageName);
|
||||
Log.d(TAG, "handlePurchase: purchase" + purchase);
|
||||
|
||||
// googlePaySuccess(1, purchase.getPurchaseToken());
|
||||
|
||||
ConsumeParams consumeParams =
|
||||
ConsumeParams.newBuilder()
|
||||
.setPurchaseToken(purchase.getPurchaseToken())
|
||||
.build();
|
||||
ConsumeResponseListener listener = new ConsumeResponseListener() {
|
||||
@Override
|
||||
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
|
||||
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
|
||||
// Handle the success of the consume operation.
|
||||
googlePaySuccess(1, purchaseToken, sku_id, packageName, 1);
|
||||
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
|
||||
googlePaySuccess(-1, "", sku_id, packageName, 1);
|
||||
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED) {
|
||||
googlePaySuccess(-3, "", sku_id, packageName, 1);
|
||||
} else {
|
||||
googlePaySuccess(-2, "", sku_id, packageName, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
billingClient.consumeAsync(consumeParams, listener);
|
||||
} else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) {
|
||||
googlePaySuccess(-4, "", "", "", 1);
|
||||
}
|
||||
}
|
||||
|
||||
//#region 登录相关方法
|
||||
|
||||
/**
|
||||
* Google登录返回
|
||||
*
|
||||
* @param completedTask
|
||||
*/
|
||||
public void HandleSignInResult(AppActivity nAppActivity, Context _context, Task<GoogleSignInAccount> completedTask) {
|
||||
try {
|
||||
InitInfo(nAppActivity, _context);
|
||||
Log.d(TAG, "HandleSignInResult: ");
|
||||
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
|
||||
GoogleLoginSuccess(1, account);
|
||||
// Signed in successfully, show authenticated UI.
|
||||
// updateUI(account);
|
||||
} catch (ApiException e) {
|
||||
// The ApiException status code indicates the detailed failure reason.
|
||||
// Please refer to the GoogleSignInStatusCodes class reference for more information.
|
||||
// updateUI(null);
|
||||
Log.d(TAG, "HandleSignInResult: signInResult:failed code=" + e.toString());
|
||||
// https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes
|
||||
// 12500 使用当前帐户登录尝试失败。
|
||||
// 12501 用户已取消登录。即用户取消了一些登录解决方案,例如帐户选择或 OAuth 同意。
|
||||
// 12502 当前正在进行登录过程,当前无法继续。例如,用户多次单击 SignInButton 并且启动了多个登录意图。
|
||||
GoogleLoginSuccess(e.getStatusCode() == 12501 ? -1 : -2, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Google服务是否可用、有弹窗
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean IsGooglePlayServices() {
|
||||
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
|
||||
int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(mActivity);
|
||||
// ConnectionResult:SUCCESS、SERVICE_MISSING、SERVICE_UPDATING、SERVICE_VERSION_UPDATE_REQUIRED、SERVICE_DISABLED、SERVICE_INVALID
|
||||
if (resultCode != ConnectionResult.SUCCESS) {
|
||||
if (googleApiAvailability.isUserResolvableError(resultCode))
|
||||
googleApiAvailability.getErrorDialog(mActivity, resultCode, mActivity.REQUEST_CODE_GOOGLE_PAY_SERVICES).show();
|
||||
else
|
||||
Log.d(TAG, "IsGooglePlayServices: This device is not supported");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Google服务是否可用、无弹窗
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean IsGooglePlayServicesNoShow() {
|
||||
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
|
||||
int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(mActivity);
|
||||
// ConnectionResult:SUCCESS、SERVICE_MISSING、SERVICE_UPDATING、SERVICE_VERSION_UPDATE_REQUIRED、SERVICE_DISABLED、SERVICE_INVALID
|
||||
if (resultCode != ConnectionResult.SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* google登录成功、回传Lua
|
||||
*
|
||||
* @param state 状态:-1.用户取消登录、1.登录成功、-2.登录异常、-3.不支持此设备
|
||||
* @param account 用户登录信息
|
||||
*/
|
||||
private void GoogleLoginSuccess(int state, GoogleSignInAccount account) {
|
||||
if (state == 1) {
|
||||
try {
|
||||
PlayersClient mPlayersClient = Games.getPlayersClient(mActivity, account);
|
||||
mPlayersClient.getCurrentPlayer()
|
||||
.addOnCompleteListener(new OnCompleteListener<Player>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Player> task) {
|
||||
if (task.isSuccessful()) {
|
||||
Log.d(TAG, "GoogleLoginSuccess onComplete:getDisplayName " + task.getResult().getDisplayName());
|
||||
googleLoginSendToLua(task.getResult().getDisplayName(), state, account);
|
||||
} else {
|
||||
Log.d(TAG, "GoogleLoginSuccess onComplete: task.getResult().getDisplayName() error ");
|
||||
googleLoginSendToLua("", state, account);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
googleLoginSendToLua("", state, account);
|
||||
Log.d(TAG, "GoogleLoginSuccess: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
// 不支持此设备
|
||||
String toast_msg = "";
|
||||
if (state == -1)
|
||||
toast_msg = "Kullanıcı girişi iptal etti";//用户取消登录
|
||||
else if (state == -2)
|
||||
toast_msg = "Oturum açma istisnası";//登录异常
|
||||
else
|
||||
toast_msg = "Bu cihaz desteklenmiyor";//不支持此设备
|
||||
|
||||
Toast.makeText(mActivity, toast_msg, Toast.LENGTH_SHORT).show();
|
||||
googleLoginSendToLua("", state, account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* google登录成功、回传Lua
|
||||
*
|
||||
* @param accountName
|
||||
* @param state 状态:-1.用户取消登录、1.登录成功、-2.登录异常、-3.不支持此设备
|
||||
* @param account 用户登录信息
|
||||
*/
|
||||
private void googleLoginSendToLua(String accountName, int state, GoogleSignInAccount account) {
|
||||
//状态|ID|token|名称|归因信息|adid_idfa|adid
|
||||
String reStr = state + "||||||";
|
||||
if (null != account) {
|
||||
if (null == accountName || accountName == "") {
|
||||
accountName = null == account.getDisplayName() ? "" : account.getDisplayName();
|
||||
accountName = null == accountName ? "" : null == account.getGivenName() ? "" : account.getGivenName();
|
||||
}
|
||||
reStr = state
|
||||
+ "|" + account.getId()
|
||||
//+ "|" + account.getIdToken()
|
||||
+ "|" + account.getServerAuthCode()
|
||||
+ "|" + accountName
|
||||
+ "|" + AdjustUtil.getInstance().getAdjustTrackerToken()
|
||||
+ "|" + ""
|
||||
+ "|" + Adjust.getAdid();
|
||||
}
|
||||
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Android_Login, reStr);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 支付相关方法
|
||||
|
||||
/**
|
||||
* 获取Google待支付商品信息
|
||||
*/
|
||||
private void getGoogleSkuDetail(String sku_id, String order_Id, int pay_type, String o_uid) {
|
||||
// 检查是否在缓存中
|
||||
if (skuDetailsMap != null && skuDetailsMap.containsKey(sku_id)) {
|
||||
SkuDetails curr_skuDetails = skuDetailsMap.get(sku_id);
|
||||
Log.d(TAG, "getGoogleSkuDetail skuDetailsMap => curr_skuDetails: ..." + curr_skuDetails);
|
||||
if (curr_skuDetails != null) {
|
||||
launchGooglePay(curr_skuDetails, order_Id, o_uid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询SKU商品是否存在
|
||||
List<String> skuList = new ArrayList<>();
|
||||
skuList.add(sku_id);
|
||||
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
|
||||
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
|
||||
billingClient.querySkuDetailsAsync(params.build(),
|
||||
new SkuDetailsResponseListener() {
|
||||
@Override
|
||||
public void onSkuDetailsResponse(BillingResult billingResult,
|
||||
List<SkuDetails> skuDetailsList) {
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse:" + billingResult + ";skuDetailsList:" + skuDetailsList);
|
||||
// Process the result.
|
||||
if (billingResult == null) {
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse: billingResult ==== null");
|
||||
return;
|
||||
}
|
||||
|
||||
int responseCode = billingResult.getResponseCode();
|
||||
String debugMessage = billingResult.getDebugMessage();
|
||||
switch (responseCode) {
|
||||
case BillingClient.BillingResponseCode.OK:
|
||||
if (skuDetailsList == null) {
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse: skuDetailsList ==== null");
|
||||
} else {
|
||||
SkuDetails curr_skuDetails = null;
|
||||
for (SkuDetails skuDetails : skuDetailsList) {
|
||||
if (null != skuDetails) {
|
||||
curr_skuDetails = skuDetails;
|
||||
if (!skuDetailsMap.containsKey(skuDetails.getSku())) {
|
||||
skuDetailsMap.put(skuDetails.getSku(), skuDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curr_skuDetails != null) {
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse => curr_skuDetails: ..." + curr_skuDetails);
|
||||
launchGooglePay(curr_skuDetails, order_Id, o_uid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED:
|
||||
case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE:
|
||||
case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE:
|
||||
case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE:
|
||||
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
|
||||
case BillingClient.BillingResponseCode.ERROR:
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse: " + responseCode + " " + debugMessage);
|
||||
googlePaySuccess(-3, "", sku_id, "", pay_type);
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.USER_CANCELED:
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse: " + responseCode + " " + debugMessage);
|
||||
googlePaySuccess(-1, "", sku_id, "", pay_type);
|
||||
break;
|
||||
// These response codes are not expected.
|
||||
case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED:
|
||||
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
|
||||
case BillingClient.BillingResponseCode.ITEM_NOT_OWNED:
|
||||
default:
|
||||
Log.d(TAG, "getGoogleSkuDetail onSkuDetailsResponse: " + responseCode + " " + debugMessage);
|
||||
googlePaySuccess(-2, "", sku_id, "", pay_type);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉起Google支付
|
||||
*/
|
||||
private void launchGooglePay(SkuDetails curr_skuDetails, String order_Id, String o_uid) {
|
||||
// if (!billingClient.isReady()) {
|
||||
// Log.e(TAG, "launchBillingFlow: BillingClient is not ready");
|
||||
// }
|
||||
|
||||
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
|
||||
.setSkuDetails(curr_skuDetails) //商品信息
|
||||
.setObfuscatedProfileId(order_Id) //订单号
|
||||
.setObfuscatedAccountId(MD5Util.MD5Encode(o_uid, "")) //系统对应的ID
|
||||
.build();
|
||||
|
||||
BillingResult billingResult = billingClient.launchBillingFlow(mActivity, billingFlowParams);
|
||||
int responseCode = billingResult.getResponseCode();
|
||||
String debugMessage = billingResult.getDebugMessage();
|
||||
Log.d(TAG, "launchGooglePay: BillingResponse " + responseCode + " " + debugMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询掉单订单信息、供LUA调用
|
||||
*/
|
||||
private void queryGoogleHistoryOrder() {
|
||||
Log.d(TAG, "queryGoogleHistoryOrder: ");
|
||||
if (billingClient != null) {
|
||||
billingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, new PurchasesResponseListener() {
|
||||
@Override
|
||||
public void onQueryPurchasesResponse(@NonNull @NotNull BillingResult billingResult, @NonNull @NotNull List<Purchase> purchases) {
|
||||
if (purchases != null) {
|
||||
for (Purchase purchase : purchases) {
|
||||
if (purchase.isAcknowledged())
|
||||
consumeProduct(purchase.getPurchaseToken());
|
||||
else {
|
||||
googlePaySuccess(1, purchase.getPurchaseToken(), purchase.getSkus().get(0), purchase.getPackageName(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Google支付结果
|
||||
*
|
||||
* @param billingResult
|
||||
* @param purchases
|
||||
*/
|
||||
private void onPurchasesUpdatedFun(BillingResult billingResult, List<Purchase> purchases, String sku_id, int pay_type) {
|
||||
if (billingResult == null) {
|
||||
Log.d(TAG, "onPurchasesUpdatedFun: null BillingResult");
|
||||
googlePaySuccess(-3, "", sku_id, "", pay_type);
|
||||
return;
|
||||
}
|
||||
int responseCode = billingResult.getResponseCode();
|
||||
String debugMessage = billingResult.getDebugMessage();
|
||||
Log.d(TAG, "onPurchasesUpdatedFun: " + responseCode + " " + debugMessage);
|
||||
switch (responseCode) {
|
||||
case BillingClient.BillingResponseCode.OK:
|
||||
if (purchases == null) {
|
||||
Log.d(TAG, "onPurchasesUpdatedFun: null purchase list");
|
||||
// processPurchases(null);
|
||||
googlePaySuccess(-3, "", sku_id, "", pay_type);
|
||||
} else {
|
||||
for (Purchase purchase : purchases) {
|
||||
// handlePurchase(purchase);
|
||||
googlePaySuccess(1, purchase.getPurchaseToken(), purchase.getSkus().get(0), purchase.getPackageName(), pay_type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.USER_CANCELED:
|
||||
Log.d(TAG, "onPurchasesUpdatedFun: User canceled the purchase");
|
||||
googlePaySuccess(-1, "", sku_id, "", pay_type);
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
|
||||
Log.d(TAG, "onPurchasesUpdatedFun: The user already owns this item");
|
||||
if (IsUseProductDetails())
|
||||
queryProductGoogleHistoryOrder();
|
||||
else
|
||||
queryGoogleHistoryOrder();
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
|
||||
googlePaySuccess(-1, "", sku_id, "", pay_type);
|
||||
Log.d(TAG, "onPurchasesUpdatedFun: Developer error means that Google Play " +
|
||||
"does not recognize the configuration. If you are just getting started, " +
|
||||
"make sure you have configured the application correctly in the " +
|
||||
"Google Play Console. The SKU product ID must match and the APK you " +
|
||||
"are using must be signed with release keys."
|
||||
);
|
||||
break;
|
||||
default:
|
||||
googlePaySuccess(-1, "", sku_id, "", pay_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* google支付完成、回传Lua
|
||||
*
|
||||
* @param state 状态:-1.用户取消支付、1.支付成功、-2.支付异常、-3.不支持此设备、-4.交易未完成
|
||||
* @param purchaseToken 购买Token、服务端用于校验并进行发放道具的校验码
|
||||
* @param sku_id 商品sku_id
|
||||
* @param packgeName 包名
|
||||
* @param pay_Type 操作方式:1.支付、2.查询掉单
|
||||
*/
|
||||
private void googlePaySuccess(int state, String purchaseToken, String sku_id, String packgeName, int pay_Type) {
|
||||
String reStr = state + "|" + " " + "|" + " " + "|" + " ";
|
||||
if (state == 1) {
|
||||
reStr = state + "|" + sku_id + "|" + packgeName + "|" + purchaseToken;
|
||||
Log.d(TAG, "googlePaySuccess:handleSignInResult:" + reStr);
|
||||
//SendToJs(EventNameUtil.Android_Pay, reStr);
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Android_Pay, reStr);
|
||||
} else {
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Android_Pay, reStr);
|
||||
//SendToJs(EventNameUtil.Android_Pay, reStr);
|
||||
// if (pay_Type == 1) {
|
||||
// String toast_msg = "";
|
||||
// if (state == -1)
|
||||
// toast_msg = "Kullanıcı ödemeyi iptal etti";//用户取消支付
|
||||
// else if (state == -2)
|
||||
// toast_msg = "Ödeme istisnası";//支付异常
|
||||
// else if (state == -3)
|
||||
// toast_msg = "Bu cihaz desteklenmiyor";//不支持此设备
|
||||
// else
|
||||
// toast_msg = "İşlem tamamlanmadı";//交易未完成
|
||||
// Toast.makeText(mActivity, toast_msg, Toast.LENGTH_SHORT).show();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 消耗商品
|
||||
*
|
||||
* @param purchaseToken 商品token
|
||||
*/
|
||||
private void consumeProduct(String purchaseToken) {
|
||||
Log.d(TAG, "consumeProduct:::" + purchaseToken);
|
||||
if (billingClient != null && billingClient.isReady()) {
|
||||
ConsumeParams consumeParams =
|
||||
ConsumeParams.newBuilder()
|
||||
.setPurchaseToken(purchaseToken)
|
||||
.build();
|
||||
ConsumeResponseListener listener = new ConsumeResponseListener() {
|
||||
@Override
|
||||
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
|
||||
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
|
||||
// Handle the success of the consume operation.
|
||||
}
|
||||
}
|
||||
};
|
||||
billingClient.consumeAsync(consumeParams, listener);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 6.0支付方法
|
||||
|
||||
/**
|
||||
* 判断ProductDetails是否可用、不可用请使用SkuDetails
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean IsUseProductDetails() {
|
||||
//在极少数情况下,某些设备无法支持 ProductDetails 和 queryProductDetailsAsync(),这通常是因为 Google Play 服务版本已过时。
|
||||
//为了确保对此场景提供适当的支持,请先针对 PRODUCT_DETAILS 功能调用 isFeatureSupported(),然后再调用 queryProductDetailsAsync。
|
||||
//如果响应为 OK,表示设备支持该功能,您可以继续调用 queryProductDetailsAsync()。
|
||||
//如果响应为 FEATURE_NOT_SUPPORTED,您可以改用 querySkuDetailsAsync() 请求可用的向后兼容产品列表。
|
||||
//如需详细了解如何使用向后兼容功能,请参阅 2022 年 5 月的订阅功能指南。
|
||||
BillingResult _billingResult = billingClient.isFeatureSupported(BillingClient.FeatureType.PRODUCT_DETAILS);
|
||||
return _billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Google待支付商品信息
|
||||
*/
|
||||
private void getGoogleProductDetail(String product_id, String order_Id, int pay_type, String o_uid) {
|
||||
// 检查是否在缓存中
|
||||
if (productDetailsMap != null && productDetailsMap.containsKey(product_id)) {
|
||||
ProductDetails curr_productDetails = productDetailsMap.get(product_id);
|
||||
Log.d(TAG, "getGoogleProductDetail productDetailsMap => curr_skuDetails: ..." + curr_productDetails);
|
||||
if (curr_productDetails != null) {
|
||||
launchProductGooglePay(curr_productDetails, order_Id, o_uid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
List<QueryProductDetailsParams.Product> productList = new ArrayList<>();
|
||||
productList.add(QueryProductDetailsParams.Product.newBuilder()
|
||||
.setProductId(product_id)
|
||||
.setProductType(BillingClient.ProductType.INAPP)
|
||||
.build());
|
||||
QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
|
||||
.setProductList(productList)
|
||||
.build();
|
||||
|
||||
billingClient.queryProductDetailsAsync(
|
||||
params,
|
||||
new ProductDetailsResponseListener() {
|
||||
public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
|
||||
// Process the result
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse:" + billingResult + ";productDetailsList:" + productDetailsList);
|
||||
if (billingResult == null) {
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse: billingResult ==== null");
|
||||
return;
|
||||
}
|
||||
|
||||
int responseCode = billingResult.getResponseCode();
|
||||
String debugMessage = billingResult.getDebugMessage();
|
||||
switch (responseCode) {
|
||||
case BillingClient.BillingResponseCode.OK:
|
||||
if (productDetailsList == null) {
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse: productDetailsList ==== null");
|
||||
} else {
|
||||
ProductDetails curr_productDetails = null;
|
||||
for (ProductDetails productDetails : productDetailsList) {
|
||||
if (null != productDetails) {
|
||||
curr_productDetails = productDetails;
|
||||
if (!productDetailsMap.containsKey(productDetails.getProductId())) {
|
||||
productDetailsMap.put(productDetails.getProductId(), productDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curr_productDetails != null) {
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse => curr_productDetails: ..." + curr_productDetails);
|
||||
launchProductGooglePay(curr_productDetails, order_Id, o_uid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED:
|
||||
case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE:
|
||||
case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE:
|
||||
case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE:
|
||||
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
|
||||
case BillingClient.BillingResponseCode.ERROR:
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse: " + responseCode + " " + debugMessage);
|
||||
googlePaySuccess(-3, "", product_id, "", pay_type);
|
||||
break;
|
||||
case BillingClient.BillingResponseCode.USER_CANCELED:
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse: " + responseCode + " " + debugMessage);
|
||||
googlePaySuccess(-1, "", product_id, "", pay_type);
|
||||
break;
|
||||
// These response codes are not expected.
|
||||
case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED:
|
||||
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
|
||||
case BillingClient.BillingResponseCode.ITEM_NOT_OWNED:
|
||||
default:
|
||||
Log.d(TAG, "getGoogleProductDetail onProductDetailsResponse: " + responseCode + " " + debugMessage);
|
||||
googlePaySuccess(-2, "", product_id, "", pay_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉起Google支付
|
||||
*/
|
||||
private void launchProductGooglePay(ProductDetails curr_productDetails, String order_Id, String o_uid) {
|
||||
//if (!billingClient.isReady()) {
|
||||
// Log.e(TAG, "launchBillingFlow: BillingClient is not ready");
|
||||
//}
|
||||
|
||||
// 获取优惠信息
|
||||
// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
|
||||
// Get the offerToken of the selected offer
|
||||
// String offerToken = curr_productDetails
|
||||
// .getSubscriptionOfferDetails()
|
||||
// .get(selectedOfferIndex)
|
||||
// .getOfferToken();
|
||||
|
||||
// 支付信息组合
|
||||
// Set the parameters for the offer that will be presented
|
||||
// in the billing flow creating separate productDetailsParamsList variable
|
||||
List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = new ArrayList<>();
|
||||
productDetailsParamsList.add(
|
||||
BillingFlowParams.ProductDetailsParams.newBuilder()
|
||||
.setProductDetails(curr_productDetails)
|
||||
// .setOfferToken(offerToken) //优惠信息
|
||||
.build()
|
||||
);
|
||||
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
|
||||
.setProductDetailsParamsList(productDetailsParamsList)
|
||||
.setObfuscatedProfileId(order_Id) //订单号
|
||||
.setObfuscatedAccountId(MD5Util.MD5Encode(o_uid, "")) //系统对应的ID
|
||||
.build();
|
||||
|
||||
// Launch the billing flow 拉起支付
|
||||
BillingResult billingResult = billingClient.launchBillingFlow(mActivity, billingFlowParams);
|
||||
int responseCode = billingResult.getResponseCode();
|
||||
String debugMessage = billingResult.getDebugMessage();
|
||||
Log.d(TAG, "launchProductGooglePay: BillingResponse " + responseCode + " " + debugMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询掉单订单信息、供LUA调用
|
||||
*/
|
||||
private void queryProductGoogleHistoryOrder() {
|
||||
Log.d(TAG, "queryProductGoogleHistoryOrder: ");
|
||||
if (billingClient != null) {
|
||||
billingClient.queryPurchasesAsync(
|
||||
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(),
|
||||
new PurchasesResponseListener() {
|
||||
public void onQueryPurchasesResponse(
|
||||
BillingResult billingResult,
|
||||
List<Purchase> purchases) {
|
||||
// Process the result
|
||||
for (Purchase purchase : purchases) {
|
||||
if (purchase.isAcknowledged())
|
||||
consumeProduct(purchase.getPurchaseToken());
|
||||
else {
|
||||
googlePaySuccess(1, purchase.getPurchaseToken(), purchase.getProducts().get(0), purchase.getPackageName(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// private void SendToJs(String eventName, String params) {
|
||||
//// mActivity.runOnGLThread(new Runnable() {
|
||||
//// @Override
|
||||
//// public void run() {
|
||||
//// Log.d(TAG, "SendToJs: " + eventName + " " + params);
|
||||
//// GetJsbBridgeWrapper().dispatchEventToScript(eventName, params);
|
||||
//// }
|
||||
//// });
|
||||
// try {
|
||||
// Log.d(TAG, "SendToJs: " + eventName + " " + params);
|
||||
// GetJsbBridgeWrapper().dispatchEventToScript(eventName, params);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
28
android/app/src/com/cocos/game/ImageLoaderUtils.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
|
||||
public class ImageLoaderUtils {
|
||||
public static boolean assertValidRequest(Context context) {
|
||||
if (context instanceof Activity) {
|
||||
Activity activity = (Activity) context;
|
||||
return !isDestroy(activity);
|
||||
} else if (context instanceof ContextWrapper) {
|
||||
ContextWrapper contextWrapper = (ContextWrapper) context;
|
||||
if (contextWrapper.getBaseContext() instanceof Activity) {
|
||||
Activity activity = (Activity) contextWrapper.getBaseContext();
|
||||
return !isDestroy(activity);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isDestroy(Activity activity) {
|
||||
if (activity == null) {
|
||||
return true;
|
||||
}
|
||||
return activity.isFinishing() || activity.isDestroyed();
|
||||
}
|
||||
}
|
||||
268
android/app/src/com/cocos/game/JSCallJava.java
Normal file
@@ -0,0 +1,268 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.adjust.sdk.Adjust;
|
||||
import com.adjust.sdk.AdjustEvent;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class JSCallJava {
|
||||
private static final String TAG = "JSCallJava";
|
||||
|
||||
public static void setOrientationPortrait() {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return;
|
||||
activity.runOnUiThread(() ->
|
||||
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
||||
);
|
||||
}
|
||||
|
||||
public static void setOrientationLandscape() {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return;
|
||||
activity.runOnUiThread(() ->
|
||||
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE)
|
||||
);
|
||||
}
|
||||
|
||||
public static void setClipboardData(String data) {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return;
|
||||
activity.runOnUiThread(() -> {
|
||||
ClipboardManager cm = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (cm != null) {
|
||||
cm.setPrimaryClip(ClipData.newPlainText("Label", data));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String GetAppVersion() {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return "";
|
||||
try {
|
||||
return activity.getPackageManager()
|
||||
.getPackageInfo(activity.getPackageName(), 0).versionName;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String GetAndroidId() {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return "";
|
||||
return Settings.Secure.getString(activity.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
}
|
||||
|
||||
public static long GetOperatorsID() {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return 0;
|
||||
try {
|
||||
TelephonyManager tm = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (tm != null) {
|
||||
String numeric = tm.getNetworkOperator();
|
||||
if (numeric != null && !numeric.isEmpty()) {
|
||||
return Long.parseLong(numeric);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void SendADJustEvent(String eventToken) {
|
||||
try {
|
||||
AdjustEvent event = new AdjustEvent(eventToken);
|
||||
Adjust.trackEvent(event);
|
||||
Log.d(TAG, "SendADJustEvent: " + eventToken);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String HasVpnTransport() {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return "0";
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (cm != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Network activeNetwork = cm.getActiveNetwork();
|
||||
if (activeNetwork != null) {
|
||||
NetworkCapabilities caps = cm.getNetworkCapabilities(activeNetwork);
|
||||
if (caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
||||
public static String getADId() {
|
||||
try {
|
||||
String adid = Adjust.getAdid();
|
||||
return adid != null ? adid : "";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void ShakePhoneOnece(int duration) {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return;
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
VibratorManager vm = (VibratorManager) activity.getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
|
||||
if (vm != null) {
|
||||
vm.getDefaultVibrator().vibrate(
|
||||
VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||
}
|
||||
} else {
|
||||
Vibrator vib = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
if (vib != null && vib.hasVibrator()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
vib.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||
} else {
|
||||
vib.vibrate(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String GetSysInfo(int sysState) {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return "";
|
||||
try {
|
||||
switch (sysState) {
|
||||
case 0: // SYSSTATE_MACADDRESS
|
||||
return getMacAddress(activity);
|
||||
case 1: // SYSSTATE_BIOSID (Android ID)
|
||||
return GetAndroidId();
|
||||
case 2: // SYSSTATE_CUPID (CPU hardware)
|
||||
return getCpuInfo();
|
||||
case 3: // SYSSTATE_HDID (Device ID)
|
||||
return getDeviceId(activity);
|
||||
case 4: // SYSSTATE_VERSION
|
||||
return GetAppVersion();
|
||||
case 5: // SYSSTATE_MODEL
|
||||
return Build.MODEL;
|
||||
case 6: // SYSSTATE_UUID
|
||||
return GetAndroidId();
|
||||
case 7: // SYSSTATE_OAID
|
||||
return getADId();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String GetChannel() {
|
||||
return "liuhaotest";
|
||||
}
|
||||
|
||||
/**
|
||||
* 从本地选择图片
|
||||
* tempDir: 保存目录
|
||||
* fileName: 文件名
|
||||
* writePath: 可写根目录
|
||||
* callbackEvent: 回调事件名
|
||||
*/
|
||||
public static void AdChooseImage(String tempDir, String fileName, String writePath, String callbackEvent) {
|
||||
AppActivity activity = AppActivity.nAppActivity;
|
||||
if (activity == null) return;
|
||||
Log.d(TAG, "AdChooseImage tempDir=" + tempDir + " fileName=" + fileName);
|
||||
activity.runOnUiThread(() -> {
|
||||
AppActivity.selectImageIndex = 0;
|
||||
AppActivity.ChooseImageDialog();
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private helpers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private static String getMacAddress(Context context) {
|
||||
try {
|
||||
WifiManager wifi = (WifiManager) context.getApplicationContext()
|
||||
.getSystemService(Context.WIFI_SERVICE);
|
||||
if (wifi != null) {
|
||||
WifiInfo info = wifi.getConnectionInfo();
|
||||
return info.getMacAddress();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getDeviceId(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
}
|
||||
try {
|
||||
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
|
||||
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
}
|
||||
}
|
||||
if (tm != null && tm.getDeviceId() != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
return tm.getImei();
|
||||
} else {
|
||||
return tm.getDeviceId();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
}
|
||||
|
||||
private static String getCpuInfo() {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec("cat /proc/cpuinfo");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("Hardware")) {
|
||||
String[] parts = line.split(":");
|
||||
if (parts.length > 1) return parts[1].trim();
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Build.HARDWARE;
|
||||
}
|
||||
}
|
||||
43
android/app/src/com/cocos/game/MD5Util.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class MD5Util {
|
||||
|
||||
private static String byteArrayToHexString(byte b[]) {
|
||||
StringBuffer resultSb = new StringBuffer();
|
||||
for (int i = 0; i < b.length; i++)
|
||||
resultSb.append(byteToHexString(b[i]));
|
||||
|
||||
return resultSb.toString();
|
||||
}
|
||||
|
||||
private static String byteToHexString(byte b) {
|
||||
int n = b;
|
||||
if (n < 0)
|
||||
n += 256;
|
||||
int d1 = n / 16;
|
||||
int d2 = n % 16;
|
||||
return hexDigits[d1] + hexDigits[d2];
|
||||
}
|
||||
|
||||
public static String MD5Encode(String origin, String charsetname) {
|
||||
String resultString = null;
|
||||
try {
|
||||
resultString = new String(origin);
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
if (charsetname == null || "".equals(charsetname))
|
||||
resultString = byteArrayToHexString(md.digest(resultString
|
||||
.getBytes()));
|
||||
else
|
||||
resultString = byteArrayToHexString(md.digest(resultString
|
||||
.getBytes(charsetname)));
|
||||
} catch (Exception exception) {
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
||||
private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
|
||||
|
||||
}
|
||||
85
android/app/src/com/cocos/game/MyApplication.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.adjust.sdk.Adjust;
|
||||
import com.adjust.sdk.AdjustAttribution;
|
||||
import com.adjust.sdk.AdjustConfig;
|
||||
import com.adjust.sdk.LogLevel;
|
||||
import com.adjust.sdk.OnAttributionChangedListener;
|
||||
import com.ddddd.one.R;
|
||||
|
||||
public class MyApplication extends Application {
|
||||
private static final String TAG = "MyApplication";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// Configure adjust SDK.
|
||||
String appToken = getString(R.string.Adjust_AppToken);
|
||||
String environment = AdjustConfig.ENVIRONMENT_PRODUCTION;
|
||||
AdjustConfig config = new AdjustConfig(this, appToken, environment);
|
||||
|
||||
// Change the log level. 如果希望禁用所有日志,请将日志级别设为 suppress:
|
||||
config.setLogLevel(LogLevel.VERBOSE);
|
||||
|
||||
// Set attribution delegate.
|
||||
config.setOnAttributionChangedListener(new OnAttributionChangedListener() {
|
||||
@Override
|
||||
public void onAttributionChanged(AdjustAttribution attribution) {
|
||||
//Log.d("cocos1", "Attribution callback called!");
|
||||
Log.d(TAG, "Attribution: " + attribution.toString());
|
||||
if (null != attribution) {
|
||||
String clickLabel = null == attribution.clickLabel ? "" : attribution.clickLabel;
|
||||
String trackerName = null == attribution.trackerName ? "" : attribution.trackerName;
|
||||
String network = null == attribution.network ? "" : attribution.network;
|
||||
String trackerToken = null == attribution.trackerToken ? "" : attribution.trackerToken;
|
||||
String adjustTT = trackerToken + "@" + trackerName + "@" + network + "@" + clickLabel;
|
||||
|
||||
EventToScriptUtil.getInstance().appCallBack(adjustTT);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialise the adjust SDK.
|
||||
Adjust.onCreate(config);
|
||||
registerActivityLifecycleCallbacks(new AdjustLifecycleCallbacks());
|
||||
}
|
||||
|
||||
// You can use this class if your app is for Android 4.0 or higher
|
||||
private static final class AdjustLifecycleCallbacks implements ActivityLifecycleCallbacks {
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
Adjust.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
Adjust.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
}
|
||||
}
|
||||
}
|
||||
198
android/app/src/com/cocos/game/MyFirebaseMessagingService.java
Normal file
@@ -0,0 +1,198 @@
|
||||
|
||||
|
||||
/**
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.cocos.game;
|
||||
|
||||
//import android.app.NotificationChannel;
|
||||
//import android.app.NotificationManager;
|
||||
//import android.app.PendingIntent;
|
||||
//import android.content.Context;
|
||||
//import android.content.Intent;
|
||||
//import android.media.RingtoneManager;
|
||||
//import android.net.Uri;
|
||||
//import android.os.Build;
|
||||
//import androidx.core.app.NotificationCompat;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.adjust.sdk.Adjust;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
//import com.google.firebase.quickstart.fcm.R;
|
||||
//
|
||||
//import androidx.work.OneTimeWorkRequest;
|
||||
//import androidx.work.WorkManager;
|
||||
|
||||
/**
|
||||
* NOTE: There can only be one service in each app that receives FCM messages. If multiple
|
||||
* are declared in the Manifest then the first one will be chosen.
|
||||
* <p>
|
||||
* In order to make this Java sample functional, you must remove the following from the Kotlin messaging
|
||||
* service in the AndroidManifest.xml:
|
||||
* <p>
|
||||
* <intent-filter>
|
||||
* <action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
* </intent-filter>
|
||||
*/
|
||||
public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
||||
|
||||
private static final String TAG = "MyFirebaseMsgService";
|
||||
|
||||
/**
|
||||
* Called when message is received.
|
||||
*
|
||||
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
|
||||
*/
|
||||
// [START receive_message]
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
// [START_EXCLUDE]
|
||||
// There are two types of messages data messages and notification messages. Data messages
|
||||
// are handled
|
||||
// here in onMessageReceived whether the app is in the foreground or background. Data
|
||||
// messages are the type
|
||||
// traditionally used with GCM. Notification messages are only received here in
|
||||
// onMessageReceived when the app
|
||||
// is in the foreground. When the app is in the background an automatically generated
|
||||
// notification is displayed.
|
||||
// When the user taps on the notification they are returned to the app. Messages
|
||||
// containing both notification
|
||||
// and data payloads are treated as notification messages. The Firebase console always
|
||||
// sends notification
|
||||
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
|
||||
// [END_EXCLUDE]
|
||||
|
||||
// TODO(developer): Handle FCM messages here.
|
||||
// Not getting messages here? See why this may be: https://goo.gl/39bRNJ
|
||||
Log.d(TAG, "From: " + remoteMessage.getFrom());
|
||||
|
||||
// // Check if message contains a data payload.
|
||||
// if (remoteMessage.getData().size() > 0) {
|
||||
// Log.d(TAG, "Message data payload: " + remoteMessage.getData());
|
||||
//
|
||||
// if (/* Check if data needs to be processed by long running job */ true) {
|
||||
// // For long-running tasks (10 seconds or more) use WorkManager.
|
||||
// scheduleJob();
|
||||
// } else {
|
||||
// // Handle message within 10 seconds
|
||||
// handleNow();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
// Check if message contains a notification payload.
|
||||
if (remoteMessage.getNotification() != null) {
|
||||
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
|
||||
}
|
||||
|
||||
// Also if you intend on generating your own notifications as a result of a received FCM
|
||||
// message, here is where that should be initiated. See sendNotification method below.
|
||||
}
|
||||
// [END receive_message]
|
||||
|
||||
|
||||
// [START on_new_token]
|
||||
|
||||
/**
|
||||
* There are two scenarios when onNewToken is called:
|
||||
* 1) When a new token is generated on initial app startup
|
||||
* 2) Whenever an existing token is changed
|
||||
* Under #2, there are three scenarios when the existing token is changed:
|
||||
* A) App is restored to a new device
|
||||
* B) User uninstalls/reinstalls the app
|
||||
* C) User clears app data
|
||||
*/
|
||||
@Override
|
||||
public void onNewToken(String token) {
|
||||
Log.d(TAG, "Refreshed token: " + token);
|
||||
Adjust.setPushToken(token, getApplicationContext());
|
||||
|
||||
// If you want to send messages to this application instance or
|
||||
// manage this apps subscriptions on the server side, send the
|
||||
// FCM registration token to your app server.
|
||||
// sendRegistrationToServer(token);
|
||||
|
||||
}
|
||||
// [END on_new_token]
|
||||
|
||||
// /**
|
||||
// * Schedule async work using WorkManager.
|
||||
// */
|
||||
// private void scheduleJob() {
|
||||
// // [START dispatch_job]
|
||||
// OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(MyWorker.class)
|
||||
// .build();
|
||||
// WorkManager.getInstance(this).beginWith(work).enqueue();
|
||||
// // [END dispatch_job]
|
||||
// }
|
||||
|
||||
/**
|
||||
* Handle time allotted to BroadcastReceivers.
|
||||
*/
|
||||
private void handleNow() {
|
||||
Log.d(TAG, "Short lived task is done.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist token to third-party servers.
|
||||
* <p>
|
||||
* Modify this method to associate the user's FCM registration token with any
|
||||
* server-side account maintained by your application.
|
||||
*
|
||||
* @param token The new token.
|
||||
*/
|
||||
private void sendRegistrationToServer(String token) {
|
||||
// TODO: Implement this method to send token to your app server.
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Create and show a simple notification containing the received FCM message.
|
||||
// *
|
||||
// * @param messageBody FCM message body received.
|
||||
// */
|
||||
// private void sendNotification(String messageBody) {
|
||||
// Intent intent = new Intent(this, MainActivity.class);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
// PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
|
||||
// PendingIntent.FLAG_ONE_SHOT);
|
||||
//
|
||||
// String channelId = getString(R.string.default_notification_channel_id);
|
||||
// Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
// NotificationCompat.Builder notificationBuilder =
|
||||
// new NotificationCompat.Builder(this, channelId)
|
||||
// .setSmallIcon(R.drawable.ic_stat_ic_notification)
|
||||
// .setContentTitle(getString(R.string.fcm_message))
|
||||
// .setContentText(messageBody)
|
||||
// .setAutoCancel(true)
|
||||
// .setSound(defaultSoundUri)
|
||||
// .setContentIntent(pendingIntent);
|
||||
//
|
||||
// NotificationManager notificationManager =
|
||||
// (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
//
|
||||
// // Since android Oreo notification channel is needed.
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// NotificationChannel channel = new NotificationChannel(channelId,
|
||||
// "Channel human readable title",
|
||||
// NotificationManager.IMPORTANCE_DEFAULT);
|
||||
// notificationManager.createNotificationChannel(channel);
|
||||
// }
|
||||
//
|
||||
// notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
|
||||
// }
|
||||
}
|
||||
547
android/app/src/com/cocos/game/PermissionsUtil.java
Normal file
@@ -0,0 +1,547 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
/**
|
||||
* 动态申请权限工具类
|
||||
*/
|
||||
|
||||
public class PermissionsUtil {
|
||||
|
||||
private PermissionsUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 危险权限,targetSdkVersion >=23必须动态申请
|
||||
*/
|
||||
public static final class Permission {
|
||||
private static final List<String> sCalendars = new ArrayList<String>(2);
|
||||
private static final List<String> sCameras = new ArrayList<String>(1);
|
||||
private static final List<String> sContactes = new ArrayList<String>(3);
|
||||
private static final List<String> sLocations = new ArrayList<String>(2);
|
||||
private static final List<String> sMicrophones = new ArrayList<String>(1);
|
||||
private static final List<String> sPhones = new ArrayList<String>(7);
|
||||
private static final List<String> sSensorses = new ArrayList<String>(1);
|
||||
private static final List<String> sSmses = new ArrayList<String>(5);
|
||||
private static final List<String> sStorages = new ArrayList<String>(2);
|
||||
|
||||
static {
|
||||
//Calendar
|
||||
sCalendars.add(Calendar.READ_CALENDAR);
|
||||
sCalendars.add(Calendar.WRITE_CALENDAR);
|
||||
//Camera
|
||||
sCameras.add(Camera.CAMERA);
|
||||
//Contacts
|
||||
sContactes.add(Contacts.WRITE_CONTACTS);
|
||||
sContactes.add(Contacts.READ_CONTACTS);
|
||||
sContactes.add(Contacts.GET_ACCOUNTS);
|
||||
//Location
|
||||
sLocations.add(Location.ACCESS_FINE_LOCATION);
|
||||
sLocations.add(Location.ACCESS_COARSE_LOCATION);
|
||||
//Microphone
|
||||
sMicrophones.add(Microphone.RECORD_AUDIO);
|
||||
//Phone
|
||||
sPhones.add(Phone.READ_PHONE_STATE);
|
||||
sPhones.add(Phone.CALL_PHONE);
|
||||
sPhones.add(Phone.READ_CALL_LOG);
|
||||
sPhones.add(Phone.WRITE_CALL_LOG);
|
||||
sPhones.add(Phone.ADD_VOICEMAIL);
|
||||
sPhones.add(Phone.USE_SIP);
|
||||
sPhones.add(Phone.PROCESS_OUTGOING_CALLS);
|
||||
//Sensors
|
||||
sSensorses.add(Sensors.BODY_SENSORS);
|
||||
//Sms
|
||||
sSmses.add(Sms.SEND_SMS);
|
||||
sSmses.add(Sms.RECEIVE_SMS);
|
||||
sSmses.add(Sms.READ_SMS);
|
||||
sSmses.add(Sms.RECEIVE_WAP_PUSH);
|
||||
sSmses.add(Sms.RECEIVE_MMS);
|
||||
//Storage
|
||||
sStorages.add(Storage.READ_EXTERNAL_STORAGE);
|
||||
sStorages.add(Storage.WRITE_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
public static final class Calendar {
|
||||
public static final String READ_CALENDAR = Manifest.permission.READ_CALENDAR;
|
||||
public static final String WRITE_CALENDAR = Manifest.permission.WRITE_CALENDAR;
|
||||
private static final String MSG = "日历";
|
||||
}
|
||||
|
||||
public static final class Camera {
|
||||
public static final String CAMERA = Manifest.permission.CAMERA;
|
||||
private static final String MSG = "kamera";//相机
|
||||
}
|
||||
|
||||
public static final class Contacts {
|
||||
public static final String READ_CONTACTS = Manifest.permission.READ_CONTACTS;
|
||||
public static final String WRITE_CONTACTS = Manifest.permission.WRITE_CONTACTS;
|
||||
public static final String GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
|
||||
private static final String MSG = "联系人";
|
||||
}
|
||||
|
||||
public static final class Location {
|
||||
public static final String ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
|
||||
public static final String ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||
private static final String MSG = "定位";
|
||||
}
|
||||
|
||||
public static final class Microphone {
|
||||
public static final String RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
|
||||
private static final String MSG = "mikrofon";//麦克风
|
||||
}
|
||||
|
||||
public static final class Phone {
|
||||
public static final String READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
|
||||
public static final String CALL_PHONE = Manifest.permission.CALL_PHONE;
|
||||
public static final String READ_CALL_LOG = Manifest.permission.READ_CALL_LOG;
|
||||
public static final String WRITE_CALL_LOG = Manifest.permission.WRITE_CALL_LOG;
|
||||
public static final String ADD_VOICEMAIL = Manifest.permission.ADD_VOICEMAIL;
|
||||
public static final String USE_SIP = Manifest.permission.USE_SIP;
|
||||
public static final String PROCESS_OUTGOING_CALLS = Manifest.permission.PROCESS_OUTGOING_CALLS;
|
||||
private static final String MSG = "电话";
|
||||
}
|
||||
|
||||
public static final class Sensors {
|
||||
public static final String BODY_SENSORS = Manifest.permission.BODY_SENSORS;
|
||||
private static final String MSG = "传感器";
|
||||
}
|
||||
|
||||
|
||||
public static final class Sms {
|
||||
public static final String SEND_SMS = Manifest.permission.SEND_SMS;
|
||||
public static final String RECEIVE_SMS = Manifest.permission.RECEIVE_SMS;
|
||||
public static final String READ_SMS = Manifest.permission.READ_SMS;
|
||||
public static final String RECEIVE_WAP_PUSH = Manifest.permission.RECEIVE_WAP_PUSH;
|
||||
public static final String RECEIVE_MMS = Manifest.permission.RECEIVE_MMS;
|
||||
private static final String MSG = "短信";
|
||||
}
|
||||
|
||||
public static final class Storage {
|
||||
public static final String READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
public static final String WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
public static final String CAMERA = Manifest.permission.CAMERA;
|
||||
private static final String MSG = "Hafıza";//存储
|
||||
}
|
||||
}
|
||||
|
||||
public static final int SETTINGS_REQ_CODE = 99;
|
||||
private static final String TAG = "PermissionsUtil";
|
||||
private static final String KEY_DENIED_PERMISSIONS = "deniedPermissions";
|
||||
private static final String KEY_REQUEST_CODE = "requestCode";
|
||||
private static final int MSG_UI_HANDLER_DEAL_DENIED_PERMISSION = 100;
|
||||
private static boolean sDebug = true;
|
||||
private Object mObject;
|
||||
private String[] mPermissions;
|
||||
private int mRequestCode;
|
||||
private String mRationaleTitle;
|
||||
private String mPositiveText = "Emin ol";//确定
|
||||
private String mNegativeText = "İptal";//取消
|
||||
private int mRequestPermissionCount = 0;//请求授权次数
|
||||
private Handler mUiHandler = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_UI_HANDLER_DEAL_DENIED_PERMISSION:
|
||||
Bundle data = msg.getData();
|
||||
int requestCode = data.getInt(KEY_REQUEST_CODE);
|
||||
String[] permissions = data.getStringArray(KEY_DENIED_PERMISSIONS);
|
||||
Object object = msg.obj;
|
||||
showAlertDialog(object, requestCode, permissions);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private PermissionsUtil(@NonNull Object object) {
|
||||
if (isObjectIllegality(object))
|
||||
throw new IllegalArgumentException("Activity or Fragment must implements IPermissionsCallback");
|
||||
mObject = object;
|
||||
}
|
||||
|
||||
public static PermissionsUtil with(@NonNull Activity activity) {
|
||||
return new PermissionsUtil(activity);
|
||||
}
|
||||
|
||||
public static PermissionsUtil with(@NonNull Fragment fragment) {
|
||||
return new PermissionsUtil(fragment);
|
||||
}
|
||||
|
||||
public static PermissionsUtil with(@NonNull android.app.Fragment fragment) {
|
||||
return new PermissionsUtil(fragment);
|
||||
}
|
||||
|
||||
public PermissionsUtil permissions(@NonNull String... permissions) {
|
||||
if (hasEmpty(permissions))
|
||||
throw new IllegalArgumentException("permissions can't contain null");
|
||||
mPermissions = permissions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil requestCode(int requestCode) {
|
||||
mRequestCode = requestCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil rationaleTitle(String title) {
|
||||
mRationaleTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil positiveText(String positiveText) {
|
||||
mPositiveText = positiveText;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil negativeText(String negativeText) {
|
||||
mNegativeText = negativeText;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil isDebug(boolean isDebug) {
|
||||
sDebug = isDebug;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil requestPermissionCount(int requestPermissionCount) {
|
||||
mRequestPermissionCount = requestPermissionCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PermissionsUtil request() {
|
||||
request(mObject, mRequestCode, mPermissions);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void request(Object object, int requestCode, String... permissions) {
|
||||
if (needRequest() && notGrantedAllPermissions(getActivity(object), permissions)) {
|
||||
if (mRequestPermissionCount > 2) {
|
||||
dealDeniedPermissions(object, requestCode, permissions);
|
||||
} else {
|
||||
List<String> unGrantedPermissionsList = createUnGrantedPermissionsList(object, permissions);
|
||||
PLog.d("request---" + "requestCode : " + requestCode + "---unGrantedPermissionsList : " + unGrantedPermissionsList);
|
||||
if (unGrantedPermissionsList.size() > 0) {
|
||||
requestPermissions(object, requestCode, listToStringArray(unGrantedPermissionsList));
|
||||
unGrantedPermissionsList.clear();
|
||||
} else {
|
||||
invokePermissionsGranted(object, requestCode, permissions);
|
||||
}
|
||||
unGrantedPermissionsList = null;
|
||||
}
|
||||
} else {
|
||||
PLog.d("request---" + "requestCode : " + requestCode + "---permissionsGranted : " + stringArrayToList(permissions));
|
||||
invokePermissionsGranted(object, requestCode, permissions);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> createUnGrantedPermissionsList(Object object, String... permissions) {
|
||||
List<String> unGrantedPermissionsList = new ArrayList<String>();
|
||||
for (String permission : permissions) {
|
||||
if (notGrantedPermission(getActivity(object), permission)) {
|
||||
unGrantedPermissionsList.add(permission);
|
||||
}
|
||||
}
|
||||
return unGrantedPermissionsList;
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void requestPermissions(Object object, int requestCode, String... permissions) {
|
||||
PLog.d("requestPermissions---" + "requestCode : " + requestCode + "---requestPermissions : " + stringArrayToList(permissions));
|
||||
if (object instanceof Activity) {
|
||||
ActivityCompat.requestPermissions((Activity) object, permissions, requestCode);
|
||||
} else if (object instanceof Fragment) {
|
||||
((Fragment) object).requestPermissions(permissions, requestCode);
|
||||
} else if (object instanceof android.app.Fragment) {
|
||||
((android.app.Fragment) object).requestPermissions(permissions, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object
|
||||
* @param requestCode
|
||||
* @param deniedPermissions denied permissions
|
||||
* @return
|
||||
*/
|
||||
private void showAlertDialog(final Object object, final int requestCode, final String... deniedPermissions) {
|
||||
PLog.d("showAlertDialog --- " + "requestCode : " + requestCode + "--- deniedPermissions : " + stringArrayToList(deniedPermissions));
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(mObject));
|
||||
if (!TextUtils.isEmpty(mRationaleTitle)) {
|
||||
builder.setTitle(mRationaleTitle);
|
||||
}
|
||||
builder.setMessage(createRationaleMsg(getActivity(object), deniedPermissions))
|
||||
.setPositiveButton(mPositiveText, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
goSetting(object);
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
.setNegativeButton(mNegativeText, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
invokePermissionsDenied(object, requestCode, deniedPermissions);
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
private boolean needRequest() {
|
||||
return Build.VERSION.SDK_INT >= 23;
|
||||
}
|
||||
|
||||
private Activity getActivity(Object object) {
|
||||
Activity activity = null;
|
||||
if (object instanceof Activity) {
|
||||
activity = (Activity) object;
|
||||
} else if (object instanceof Fragment) {
|
||||
activity = ((Fragment) object).getActivity();
|
||||
} else if (object instanceof android.app.Fragment) {
|
||||
activity = ((android.app.Fragment) object).getActivity();
|
||||
}
|
||||
return activity;
|
||||
}
|
||||
|
||||
public boolean grantedPermission(Activity activity, String permission) {
|
||||
return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public boolean notGrantedPermission(Activity activity, String permission) {
|
||||
return !grantedPermission(activity, permission);
|
||||
}
|
||||
|
||||
public boolean grantedAllPermissions(Activity activity, String... permissions) {
|
||||
for (String permission : permissions) {
|
||||
if (notGrantedPermission(activity, permission)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean notGrantedAllPermissions(Activity activity, String... permissions) {
|
||||
return !grantedAllPermissions(activity, permissions);
|
||||
}
|
||||
|
||||
private void dealDeniedPermissions(Object object, int requestCode, String... deniedPermissions) {
|
||||
PLog.d("dealDeniedPermissions --- " + "requestCode : " + requestCode + "--- deniedPermissions : " + stringArrayToList(deniedPermissions));
|
||||
Message message = mUiHandler.obtainMessage();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putStringArray(KEY_DENIED_PERMISSIONS, deniedPermissions);
|
||||
bundle.putInt(KEY_REQUEST_CODE, requestCode);
|
||||
message.setData(bundle);
|
||||
message.obj = object;
|
||||
message.what = MSG_UI_HANDLER_DEAL_DENIED_PERMISSION;
|
||||
mUiHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
private boolean isObjectLegal(Object object) {
|
||||
return (object instanceof IPermissionsCallback);
|
||||
}
|
||||
|
||||
private boolean isObjectIllegality(Object object) {
|
||||
return !isObjectLegal(object);
|
||||
}
|
||||
|
||||
private boolean hasEmpty(String... strings) {
|
||||
boolean hasEmpty = false;
|
||||
if (strings != null && strings.length > 0) {
|
||||
for (String s : strings) {
|
||||
if (TextUtils.isEmpty(s)) {
|
||||
hasEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hasEmpty = true;
|
||||
}
|
||||
return hasEmpty;
|
||||
}
|
||||
|
||||
private String[] listToStringArray(List<String> stringList) {
|
||||
return stringList.toArray(new String[stringList.size()]);
|
||||
}
|
||||
|
||||
private List<String> stringArrayToList(String[] strings) {
|
||||
return Arrays.asList(strings);
|
||||
}
|
||||
|
||||
private String getAppName(Context context) {
|
||||
String appName = "";
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
try {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
|
||||
appName = (String) packageManager.getApplicationLabel(applicationInfo);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return appName;
|
||||
}
|
||||
|
||||
private String createRationaleMsg(Context context, String... permissions) {
|
||||
String permissionsMsg = createPermissionsMsg(permissions);
|
||||
permissionsMsg = permissionsMsg.substring(0, permissionsMsg.length() - 1);
|
||||
// return getAppName(context) + "需要" + permissionsMsg + "权限,是否去设置";
|
||||
return getAppName(context) + permissionsMsg + " iznine ihtiyacınız var,ayarlanıp ayarlanmayacağı?";
|
||||
}
|
||||
|
||||
private String createPermissionsMsg(String... permissions) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean grantedCalendar = false;
|
||||
boolean grantedCamera = false;
|
||||
boolean grantedContacts = false;
|
||||
boolean grantedLocation = false;
|
||||
boolean grantedMicrophone = false;
|
||||
boolean grantedPhone = false;
|
||||
boolean grantedSensors = false;
|
||||
boolean grantedSms = false;
|
||||
boolean grantedStorage = false;
|
||||
for (String permission : permissions) {
|
||||
if (!grantedCalendar && Permission.sCalendars.contains(permission)) {
|
||||
builder.append(Permission.Calendar.MSG);
|
||||
builder.append("、");
|
||||
grantedCalendar = true;
|
||||
}
|
||||
if (!grantedCamera && Permission.sCameras.contains(permission)) {
|
||||
builder.append(Permission.Camera.MSG);
|
||||
builder.append("、");
|
||||
grantedCamera = true;
|
||||
}
|
||||
if (!grantedContacts && Permission.sContactes.contains(permission)) {
|
||||
builder.append(Permission.Contacts.MSG);
|
||||
builder.append("、");
|
||||
grantedContacts = true;
|
||||
}
|
||||
if (!grantedLocation && Permission.sLocations.contains(permission)) {
|
||||
builder.append(Permission.Location.MSG);
|
||||
builder.append("、");
|
||||
grantedLocation = true;
|
||||
}
|
||||
if (!grantedMicrophone && Permission.sMicrophones.contains(permission)) {
|
||||
builder.append(Permission.Microphone.MSG);
|
||||
builder.append("、");
|
||||
grantedMicrophone = true;
|
||||
}
|
||||
if (!grantedPhone && Permission.sPhones.contains(permission)) {
|
||||
builder.append(Permission.Phone.MSG);
|
||||
builder.append("、");
|
||||
grantedPhone = true;
|
||||
}
|
||||
if (!grantedSensors && Permission.sSensorses.contains(permission)) {
|
||||
builder.append(Permission.Sensors.MSG);
|
||||
builder.append("、");
|
||||
grantedSensors = true;
|
||||
}
|
||||
if (!grantedSms && Permission.sSmses.contains(permission)) {
|
||||
builder.append(Permission.Sms.MSG);
|
||||
builder.append("、");
|
||||
grantedSms = true;
|
||||
}
|
||||
if (!grantedStorage && Permission.sStorages.contains(permission)) {
|
||||
builder.append(Permission.Storage.MSG);
|
||||
builder.append("、");
|
||||
grantedStorage = true;
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private IPermissionsCallback getPermissionsCallback(Object object) {
|
||||
return (IPermissionsCallback) object;
|
||||
}
|
||||
|
||||
private void invokePermissionsGranted(Object object, int requestCode, String... permissions) {
|
||||
getPermissionsCallback(object).onPermissionsGranted(requestCode, permissions);
|
||||
}
|
||||
|
||||
private void invokePermissionsDenied(Object object, int requestCode, String... permissions) {
|
||||
getPermissionsCallback(object).onPermissionsDenied(requestCode, permissions);
|
||||
}
|
||||
|
||||
public interface IPermissionsCallback {
|
||||
void onPermissionsGranted(int requestCode, String... permission);
|
||||
|
||||
void onPermissionsDenied(int requestCode, String... permission);
|
||||
}
|
||||
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == mRequestCode) {
|
||||
List<String> deniedPermissions = new ArrayList<String>();
|
||||
for (int i = 0; i < grantResults.length; i++) {
|
||||
if (grantResults[i] != PackageManager.PERMISSION_GRANTED)
|
||||
deniedPermissions.add(permissions[i]);
|
||||
}
|
||||
PLog.d("onRequestPermissionsResult--- " + "requestCode : " + requestCode + "--- deniedPermissions : " + deniedPermissions);
|
||||
if (deniedPermissions.size() > 0) {
|
||||
dealDeniedPermissions(mObject, requestCode, listToStringArray(deniedPermissions));
|
||||
} else {
|
||||
invokePermissionsGranted(mObject, requestCode, permissions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == SETTINGS_REQ_CODE) {
|
||||
List<String> unGrantedPermissionsList = createUnGrantedPermissionsList(mObject, mPermissions);
|
||||
PLog.d("onActivityResult --- " + "requestCode : " + requestCode + "---" + "unGrantedPermissionsList : " + unGrantedPermissionsList);
|
||||
if (unGrantedPermissionsList.size() > 0) {
|
||||
invokePermissionsDenied(mObject, mRequestCode, listToStringArray(unGrantedPermissionsList));
|
||||
} else {
|
||||
invokePermissionsGranted(mObject, mRequestCode, mPermissions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void goSetting(Object object) {
|
||||
PLog.d("goSetting");
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
Uri uri = Uri.fromParts("package", getActivity(object).getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
if (object instanceof Activity) {
|
||||
((Activity) object).startActivityForResult(intent, SETTINGS_REQ_CODE);
|
||||
} else if (object instanceof Fragment) {
|
||||
((Fragment) object).startActivityForResult(intent, SETTINGS_REQ_CODE);
|
||||
} else if (object instanceof android.app.Fragment) {
|
||||
((android.app.Fragment) object).startActivityForResult(intent, SETTINGS_REQ_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
static final class PLog {
|
||||
private static void d(String msg) {
|
||||
if (sDebug)
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
|
||||
private static void e(String msg) {
|
||||
if (sDebug)
|
||||
Log.e(TAG, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
406
android/app/src/com/cocos/game/PictureSelectlucksiege.java
Normal file
@@ -0,0 +1,406 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.ConstraintSet;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.luck.lib.camerax.CameraImageEngine;
|
||||
import com.luck.lib.camerax.SimpleCameraX;
|
||||
import com.luck.picture.lib.config.PictureMimeType;
|
||||
import com.luck.picture.lib.config.SelectLimitType;
|
||||
import com.luck.picture.lib.config.SelectorConfig;
|
||||
import com.luck.picture.lib.dialog.RemindDialog;
|
||||
import com.luck.picture.lib.engine.CompressFileEngine;
|
||||
import com.luck.picture.lib.engine.CropFileEngine;
|
||||
import com.luck.picture.lib.engine.UriToFileTransformEngine;
|
||||
import com.luck.picture.lib.entity.LocalMedia;
|
||||
import com.luck.picture.lib.interfaces.OnCallbackListener;
|
||||
import com.luck.picture.lib.interfaces.OnCameraInterceptListener;
|
||||
import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener;
|
||||
import com.luck.picture.lib.interfaces.OnPermissionDeniedListener;
|
||||
import com.luck.picture.lib.interfaces.OnPermissionDescriptionListener;
|
||||
import com.luck.picture.lib.interfaces.OnSelectLimitTipsListener;
|
||||
import com.luck.picture.lib.permissions.PermissionConfig;
|
||||
import com.luck.picture.lib.permissions.PermissionUtil;
|
||||
import com.luck.picture.lib.style.SelectMainStyle;
|
||||
import com.luck.picture.lib.utils.DateUtils;
|
||||
import com.luck.picture.lib.utils.DensityUtil;
|
||||
import com.luck.picture.lib.utils.SandboxTransformUtils;
|
||||
import com.luck.picture.lib.utils.ToastUtils;
|
||||
import com.luck.picture.lib.widget.MediumBoldTextView;
|
||||
import com.yalantis.ucrop.UCrop;
|
||||
import com.yalantis.ucrop.UCropImageEngine;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import top.zibin.luban.CompressionPredicate;
|
||||
import top.zibin.luban.Luban;
|
||||
import top.zibin.luban.OnNewCompressListener;
|
||||
import top.zibin.luban.OnRenameListener;
|
||||
|
||||
import com.ddddd.one.R;
|
||||
|
||||
public class PictureSelectlucksiege {
|
||||
|
||||
private final static String TAG_EXPLAIN_VIEW = "TAG_EXPLAIN_VIEW";
|
||||
|
||||
/**
|
||||
* 自定义压缩
|
||||
*/
|
||||
public static class ImageFileCompressEngine implements CompressFileEngine {
|
||||
|
||||
@Override
|
||||
public void onStartCompress(Context context, ArrayList<Uri> source, OnKeyValueResultCallbackListener call) {
|
||||
Luban.with(context).load(source).ignoreBy(100).setRenameListener(new OnRenameListener() {
|
||||
@Override
|
||||
public String rename(String filePath) {
|
||||
int indexOf = filePath.lastIndexOf(".");
|
||||
String postfix = indexOf != -1 ? filePath.substring(indexOf) : ".jpg";
|
||||
String path_ = DateUtils.getCreateFileName("CMP_") + postfix;
|
||||
Log.i("onResult", "rename: " + path_);
|
||||
return path_;
|
||||
}
|
||||
}).filter(new CompressionPredicate() {
|
||||
@Override
|
||||
public boolean apply(String path) {
|
||||
if (PictureMimeType.isUrlHasImage(path) && !PictureMimeType.isHasHttp(path)) {
|
||||
return true;
|
||||
}
|
||||
return !PictureMimeType.isUrlHasGif(path);
|
||||
}
|
||||
}).setCompressListener(new OnNewCompressListener() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(String source, File compressFile) {
|
||||
if (call != null) {
|
||||
Log.i("onResult", "onSuccess: xxx ");
|
||||
call.onCallback(source, compressFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String source, Throwable e) {
|
||||
if (call != null) {
|
||||
Log.i("onResult", "onError: xxx ");
|
||||
call.onCallback(source, null);
|
||||
}
|
||||
}
|
||||
}).launch();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义裁剪
|
||||
*/
|
||||
public static class ImageFileCropEngine implements CropFileEngine {
|
||||
@Override
|
||||
public void onStartCrop(Fragment fragment, Uri srcUri, Uri destinationUri, ArrayList<String> dataSource, int requestCode) {
|
||||
UCrop.Options options = PictureSelectlucksiege.buildOptions();
|
||||
UCrop uCrop = UCrop.of(srcUri, destinationUri, dataSource);
|
||||
uCrop.withOptions(options);
|
||||
uCrop.setImageEngine(new UCropImageEngine() {
|
||||
@Override
|
||||
public void loadImage(Context context, String url, ImageView imageView) {
|
||||
if (!ImageLoaderUtils.assertValidRequest(context)) {
|
||||
return;
|
||||
}
|
||||
Glide.with(context).load(url).override(240, 240).into(imageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadImage(Context context, Uri url, int maxWidth, int maxHeight, OnCallbackListener<Bitmap> call) {
|
||||
Glide.with(context).asBitmap().load(url).override(maxWidth, maxHeight).into(new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
||||
if (call != null) {
|
||||
call.onCall(resource);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
if (call != null) {
|
||||
call.onCall(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
uCrop.start(fragment.requireActivity(), fragment, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截自定义提示
|
||||
*/
|
||||
public static class MeOnSelectLimitTipsListener implements OnSelectLimitTipsListener {
|
||||
|
||||
@Override
|
||||
public boolean onSelectLimitTips(Context context, @Nullable LocalMedia media, SelectorConfig config, int limitType) {
|
||||
if (limitType == SelectLimitType.SELECT_MIN_SELECT_LIMIT) {
|
||||
ToastUtils.showToast(context, "图片最少不能低于" + config.minSelectNum + "张");
|
||||
return true;
|
||||
} else if (limitType == SelectLimitType.SELECT_MIN_VIDEO_SELECT_LIMIT) {
|
||||
ToastUtils.showToast(context, "视频最少不能低于" + config.minVideoSelectNum + "个");
|
||||
return true;
|
||||
} else if (limitType == SelectLimitType.SELECT_MIN_AUDIO_SELECT_LIMIT) {
|
||||
ToastUtils.showToast(context, "音频最少不能低于" + config.minAudioSelectNum + "个");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加权限说明
|
||||
*/
|
||||
public static class MeOnPermissionDescriptionListener implements OnPermissionDescriptionListener {
|
||||
|
||||
@Override
|
||||
public void onPermissionDescription(Fragment fragment, String[] permissionArray) {
|
||||
View rootView = fragment.requireView();
|
||||
if (rootView instanceof ViewGroup) {
|
||||
addPermissionDescription(false, (ViewGroup) rootView, permissionArray);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(Fragment fragment) {
|
||||
removePermissionDescription((ViewGroup) fragment.requireView());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限拒绝后回调
|
||||
*/
|
||||
public static class MeOnPermissionDeniedListener implements OnPermissionDeniedListener {
|
||||
|
||||
@Override
|
||||
public void onDenied(Fragment fragment, String[] permissionArray,
|
||||
int requestCode, OnCallbackListener<Boolean> call) {
|
||||
String tips;
|
||||
if (TextUtils.equals(permissionArray[0], PermissionConfig.CAMERA[0])) {
|
||||
tips = "Kamera erişimi yok\nKamera işlevinin kullanılamamasıyla sonuçlanacaktır.";// "缺少相机权限\n可能会导致不能使用摄像头功能";
|
||||
} else if (TextUtils.equals(permissionArray[0], Manifest.permission.RECORD_AUDIO)) {
|
||||
tips = "Ses kayıt erİşimi yok\nCihazınızdaki ses medya içeriği ve dosyalara erişin";// "缺少录音权限\n访问您设备上的音频、媒体内容和文件";
|
||||
} else {
|
||||
tips = "Depolama erişmi yok\nCihazınızdaki fotoğraf ortamı içeriğine ve dosyalara erişin";//"缺少存储权限\n访问您设备上的照片、媒体内容和文件";
|
||||
}
|
||||
RemindDialog dialog = RemindDialog.buildDialog(fragment.getContext(), tips);
|
||||
dialog.setButtonText("Ayarlara git");//去设置
|
||||
dialog.setButtonTextColor(0xFF7D7DFF);
|
||||
dialog.setContentTextColor(0xFF333333);
|
||||
dialog.setOnDialogClickListener(new RemindDialog.OnDialogClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
PermissionUtil.goIntentSetting(fragment, requestCode);
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义沙盒文件处理
|
||||
*/
|
||||
public static class MeSandboxFileEngine implements UriToFileTransformEngine {
|
||||
|
||||
@Override
|
||||
public void onUriToFileAsyncTransform(Context context, String srcPath, String mineType, OnKeyValueResultCallbackListener call) {
|
||||
if (call != null) {
|
||||
call.onCallback(srcPath, SandboxTransformUtils.copyPathToSandbox(context, srcPath, mineType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义拍照
|
||||
*/
|
||||
public static class MeOnCameraInterceptListener implements OnCameraInterceptListener {
|
||||
@Override
|
||||
public void openCamera(Fragment fragment, int cameraMode, int requestCode) {
|
||||
SimpleCameraX camera = SimpleCameraX.of();
|
||||
camera.isAutoRotation(true);//是否自动纠偏
|
||||
camera.setCameraMode(cameraMode);//相机模式
|
||||
camera.setVideoFrameRate(25);
|
||||
//camera.setVideoBitRate(3 * 1024 * 1024);
|
||||
//camera.isDisplayRecordChangeTime(true);
|
||||
//camera.isManualFocusCameraPreview(cb_camera_focus.isChecked());
|
||||
camera.isZoomCameraPreview(true);//是否可缩放相机
|
||||
camera.setOutputPathDir(getSandboxCameraOutputPath());
|
||||
//camera.setPermissionDeniedListener(getSimpleXPermissionDeniedListener());
|
||||
//camera.setPermissionDescriptionListener(getSimpleXPermissionDescriptionListener());
|
||||
camera.setImageEngine(new CameraImageEngine() {
|
||||
@Override
|
||||
public void loadImage(Context context, String url, ImageView imageView) {
|
||||
Glide.with(context).load(url).into(imageView);
|
||||
}
|
||||
});
|
||||
camera.start(fragment.requireActivity(), fragment, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加权限说明
|
||||
*
|
||||
* @param viewGroup
|
||||
* @param permissionArray
|
||||
*/
|
||||
private static void addPermissionDescription(boolean isHasSimpleXCamera, ViewGroup viewGroup, String[] permissionArray) {
|
||||
int dp10 = DensityUtil.dip2px(viewGroup.getContext(), 10);
|
||||
int dp15 = DensityUtil.dip2px(viewGroup.getContext(), 15);
|
||||
MediumBoldTextView view = new MediumBoldTextView(viewGroup.getContext());
|
||||
view.setTag(TAG_EXPLAIN_VIEW);
|
||||
view.setTextSize(14);
|
||||
view.setTextColor(Color.parseColor("#333333"));
|
||||
view.setPadding(dp10, dp15, dp10, dp15);
|
||||
|
||||
String title;
|
||||
String explain;
|
||||
|
||||
if (TextUtils.equals(permissionArray[0], PermissionConfig.CAMERA[0])) {
|
||||
title = "Kamera izinlerini kullanma açıklaması";//"相机权限使用说明";
|
||||
explain = "Fotoğraf çekmek/Video kaydetmek için";//"相机权限使用说明\n用户app用于拍照/录视频";
|
||||
} else if (TextUtils.equals(permissionArray[0], Manifest.permission.RECORD_AUDIO)) {
|
||||
if (isHasSimpleXCamera) {
|
||||
title = "Mikrofon izinlerini kullanma açıklaması";//""麦克风权限使用说明";
|
||||
explain = "Video kaydederken ses toplama için";//""麦克风权限使用说明\n用户app用于录视频时采集声音";
|
||||
} else {
|
||||
title = "Ses kayıt izinlerini kullanma açıklaması";//"录音权限使用说明";
|
||||
explain = "Ses toplama için";//"录音权限使用说明\n用户app用于采集声音";
|
||||
}
|
||||
} else {
|
||||
title = "Depolama izinlerini kullanma açıklaması";// "存储权限使用说明";
|
||||
explain = "yazma/indirme/kaydetme/okuma/değiştirme/video/dosya ve bilgiler ve resimleri silmek için kullanılır";//"存储权限使用说明\n用户app写入/下载/保存/读取/修改/删除图片、视频、文件等信息";
|
||||
}
|
||||
int startIndex = 0;
|
||||
int endOf = startIndex + title.length();
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(explain);
|
||||
builder.setSpan(new AbsoluteSizeSpan(DensityUtil.dip2px(viewGroup.getContext(), 16)), startIndex, endOf, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
builder.setSpan(new ForegroundColorSpan(0xFF333333), startIndex, endOf, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
view.setText(builder);
|
||||
view.setBackground(ContextCompat.getDrawable(viewGroup.getContext(), R.drawable.ps_permission));
|
||||
|
||||
if (isHasSimpleXCamera) {
|
||||
RelativeLayout.LayoutParams layoutParams =
|
||||
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.topMargin = DensityUtil.getStatusBarHeight(viewGroup.getContext());
|
||||
layoutParams.leftMargin = dp10;
|
||||
layoutParams.rightMargin = dp10;
|
||||
viewGroup.addView(view, layoutParams);
|
||||
} else {
|
||||
ConstraintLayout.LayoutParams layoutParams =
|
||||
new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.topToBottom = R.id.title_bar;
|
||||
layoutParams.leftToLeft = ConstraintSet.PARENT_ID;
|
||||
layoutParams.leftMargin = dp10;
|
||||
layoutParams.rightMargin = dp10;
|
||||
viewGroup.addView(view, layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除权限说明
|
||||
*
|
||||
* @param viewGroup
|
||||
*/
|
||||
private static void removePermissionDescription(ViewGroup viewGroup) {
|
||||
View tagExplainView = viewGroup.findViewWithTag(TAG_EXPLAIN_VIEW);
|
||||
viewGroup.removeView(tagExplainView);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配制UCrop,可根据需求自我扩展
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static UCrop.Options buildOptions() {
|
||||
UCrop.Options options = new UCrop.Options();
|
||||
options.setHideBottomControls(true);//设置为true以隐藏底部控件(默认显示)
|
||||
options.setFreeStyleCropEnabled(true);//允许用户调整裁剪边界的大小
|
||||
options.setShowCropFrame(true);//图像顶部看到裁剪框矩形
|
||||
options.setShowCropGrid(true);//如果希望在图像顶部看到裁剪网格/指导线,请设置为true
|
||||
options.setCircleDimmedLayer(true);//如果希望暗显层内部有一个圆圈,请将其设置为true
|
||||
options.withAspectRatio(240, 240);//设置裁剪边界的纵横比。用户将看不到带有其他比例选项的菜单。
|
||||
// options.setCropOutputPathDir(getSandboxPath());
|
||||
options.isCropDragSmoothToCenter(true);//自动居中裁剪和拖动
|
||||
// options.setSkipCropMimeType(getNotSupportCrop());//Skip crop mimeType
|
||||
// options.isForbidCropGifWebp(cb_not_gif.isChecked());//你需要支持剪切动态图形吗gif或webp
|
||||
// options.isForbidSkipMultipleCrop(true);//切割多个图纸时禁止跳过
|
||||
options.setMaxScaleMultiplier(100);//该方法设置用于从最小图像比例计算最大图像比例的乘数
|
||||
// if (selectorStyle != null && selectorStyle.getSelectMainStyle().getStatusBarColor() != 0) {
|
||||
// SelectMainStyle mainStyle = selectorStyle.getSelectMainStyle();
|
||||
// boolean isDarkStatusBarBlack = mainStyle.isDarkStatusBarBlack();
|
||||
// int statusBarColor = mainStyle.getStatusBarColor();
|
||||
// options.isDarkStatusBarBlack(isDarkStatusBarBlack);
|
||||
// if (StyleUtils.checkStyleValidity(statusBarColor)) {
|
||||
// options.setStatusBarColor(statusBarColor);
|
||||
// options.setToolbarColor(statusBarColor);
|
||||
// } else {
|
||||
// options.setStatusBarColor(ContextCompat.getColor(getContext(), R.color.ps_color_grey));
|
||||
// options.setToolbarColor(ContextCompat.getColor(getContext(), R.color.ps_color_grey));
|
||||
// }
|
||||
// TitleBarStyle titleBarStyle = selectorStyle.getTitleBarStyle();
|
||||
// if (StyleUtils.checkStyleValidity(titleBarStyle.getTitleTextColor())) {
|
||||
// options.setToolbarWidgetColor(titleBarStyle.getTitleTextColor());
|
||||
// } else {
|
||||
// options.setToolbarWidgetColor(ContextCompat.getColor(getContext(), R.color.ps_color_white));
|
||||
// }
|
||||
// } else {
|
||||
// options.setStatusBarColor(ContextCompat.getColor(getContext(), R.color.ps_color_grey));
|
||||
// options.setToolbarColor(ContextCompat.getColor(getContext(), R.color.ps_color_grey));
|
||||
// options.setToolbarWidgetColor(ContextCompat.getColor(getContext(), R.color.ps_color_white));
|
||||
// }
|
||||
options.setStatusBarColor(ContextCompat.getColor(AppActivity.nAppActivity, R.color.ps_color_grey));
|
||||
options.setToolbarColor(ContextCompat.getColor(AppActivity.nAppActivity, R.color.ps_color_grey));
|
||||
options.setToolbarWidgetColor(ContextCompat.getColor(AppActivity.nAppActivity, R.color.ps_color_white));
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建相机自定义输出目录
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static String getSandboxCameraOutputPath() {
|
||||
File externalFilesDir = AppActivity.nAppActivity.getExternalFilesDir("");
|
||||
File customFile = new File(externalFilesDir.getAbsolutePath(), "Sandbox");
|
||||
if (!customFile.exists()) {
|
||||
customFile.mkdirs();
|
||||
}
|
||||
return customFile.getAbsolutePath() + File.separator;
|
||||
}
|
||||
}
|
||||
153
android/app/src/com/cocos/game/ShakeDetector.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
|
||||
/**
|
||||
* 用于检测手机摇晃
|
||||
*
|
||||
* @author 郑智仁
|
||||
* @see <a href="http://blog.csdn.net/zhengzhiren" mce_href="http://blog.csdn.net/zhengzhiren">Blog</a>
|
||||
*/
|
||||
public class ShakeDetector implements SensorEventListener {
|
||||
/**
|
||||
* 检测的时间间隔
|
||||
*/
|
||||
static final int UPDATE_INTERVAL = 100;
|
||||
/**
|
||||
* 上一次检测的时间
|
||||
*/
|
||||
long mLastUpdateTime;
|
||||
/**
|
||||
* 上一次检测时,加速度在x、y、z方向上的分量,用于和当前加速度比较求差。
|
||||
*/
|
||||
float mLastX, mLastY, mLastZ;
|
||||
float[] poses = new float[3];
|
||||
Context mContext;
|
||||
SensorManager mSensorManager;
|
||||
ArrayList<OnShakeListener> mListeners;
|
||||
/**
|
||||
* 摇晃检测阈值,决定了对摇晃的敏感程度,越小越敏感。
|
||||
*/
|
||||
public int shakeThreshold = 300;
|
||||
|
||||
public ShakeDetector(Context context) {
|
||||
mContext = context;
|
||||
mSensorManager = (SensorManager) context
|
||||
.getSystemService(Context.SENSOR_SERVICE);
|
||||
mListeners = new ArrayList<OnShakeListener>();
|
||||
|
||||
}
|
||||
|
||||
public float[] getposes() {
|
||||
return poses;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* 当摇晃事件发生时,接收通知
|
||||
*/
|
||||
public interface OnShakeListener {
|
||||
/**
|
||||
* 当手机摇晃时被调用
|
||||
*/
|
||||
void onShake();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册OnShakeListener,当摇晃时接收通知
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void registerOnShakeListener(OnShakeListener listener) {
|
||||
if (mListeners.contains(listener))
|
||||
return;
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除已经注册的OnShakeListener
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void unregisterOnShakeListener(OnShakeListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动摇晃检测
|
||||
*/
|
||||
public void start() {
|
||||
if (mSensorManager == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
Sensor sensor = mSensorManager
|
||||
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
if (sensor == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
boolean success = mSensorManager.registerListener(this, sensor,
|
||||
SensorManager.SENSOR_DELAY_GAME);
|
||||
if (!success) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止摇晃检测
|
||||
*/
|
||||
public void stop() {
|
||||
if (mSensorManager != null)
|
||||
mSensorManager.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long diffTime = currentTime - mLastUpdateTime;
|
||||
if (diffTime < UPDATE_INTERVAL)
|
||||
return;
|
||||
mLastUpdateTime = currentTime;
|
||||
float x = event.values[0];
|
||||
float y = event.values[1];
|
||||
float z = event.values[2];
|
||||
float deltaX = x - mLastX;
|
||||
float deltaY = y - mLastY;
|
||||
float deltaZ = z - mLastZ;
|
||||
mLastX = x;
|
||||
mLastY = y;
|
||||
mLastZ = z;
|
||||
float delta = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ
|
||||
* deltaZ);
|
||||
|
||||
delta = delta * 10000 / diffTime;
|
||||
// Log.d("delta", "解析delta,: " + delta + "diffTime :" + diffTime);
|
||||
if (delta > shakeThreshold) { // 当加速度的差值大于指定的阈值,认为这是一个摇晃
|
||||
this.notifyListeners();
|
||||
}
|
||||
|
||||
poses[0] = x;
|
||||
poses[1] = y;
|
||||
poses[2] = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当摇晃事件发生时,通知所有的listener
|
||||
*/
|
||||
private void notifyListeners() {
|
||||
for (OnShakeListener listener : mListeners) {
|
||||
listener.onShake();
|
||||
}
|
||||
}
|
||||
}
|
||||
469
android/app/src/com/cocos/game/ZegoUtil.java
Normal file
@@ -0,0 +1,469 @@
|
||||
package com.cocos.game;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.cocos.lib.JsbBridgeWrapper;
|
||||
import com.ddddd.one.R;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import im.zego.zegoexpress.ZegoExpressEngine;
|
||||
import im.zego.zegoexpress.callback.IZegoEventHandler;
|
||||
import im.zego.zegoexpress.constants.ZegoPlayerState;
|
||||
import im.zego.zegoexpress.constants.ZegoPublisherState;
|
||||
import im.zego.zegoexpress.constants.ZegoRoomStateChangedReason;
|
||||
import im.zego.zegoexpress.constants.ZegoScenario;
|
||||
import im.zego.zegoexpress.constants.ZegoUpdateType;
|
||||
import im.zego.zegoexpress.entity.ZegoEngineConfig;
|
||||
import im.zego.zegoexpress.entity.ZegoEngineProfile;
|
||||
import im.zego.zegoexpress.entity.ZegoStream;
|
||||
import im.zego.zegoexpress.entity.ZegoUser;
|
||||
|
||||
public class ZegoUtil {
|
||||
private static final String TAG = "ZegoUtil";
|
||||
private static ZegoUtil sInstance = null;
|
||||
|
||||
public static ZegoUtil getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new ZegoUtil();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
// JAVA
|
||||
private JsbBridgeWrapper jbw = null;
|
||||
|
||||
public JsbBridgeWrapper GetJsbBridgeWrapper() {
|
||||
if (jbw == null) {
|
||||
jbw = JsbBridgeWrapper.getInstance();
|
||||
}
|
||||
return jbw;
|
||||
}
|
||||
|
||||
private static Context mContext;
|
||||
private static AppActivity mActivity;
|
||||
|
||||
/**
|
||||
* 初始化信息
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private static void InitInfo(AppActivity activity, Context _context) {
|
||||
if (mActivity == null)
|
||||
mActivity = activity;
|
||||
if (mContext == null)
|
||||
mContext = _context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义 SDK 引擎对象
|
||||
*/
|
||||
private ZegoExpressEngine zegoExpressEngine;
|
||||
/**
|
||||
* 加入频道json字符串
|
||||
*/
|
||||
public static String ZegoJoinJsonStr = "";
|
||||
private static List<ZegoStream> ZegoStreamList = new ArrayList<>();
|
||||
private static List<String> CloseZegoStreamList = new ArrayList<>();
|
||||
private static boolean isClosePublishingStream = true;
|
||||
|
||||
public void zegoDestroyEngine() {
|
||||
if (zegoExpressEngine != null) {
|
||||
ZegoJoinJsonStr = "";
|
||||
ZegoStreamList.clear();
|
||||
CloseZegoStreamList.clear();
|
||||
isClosePublishingStream = true;
|
||||
// 退出全部房间
|
||||
zegoExpressEngine.logoutRoom();
|
||||
/** 销毁 SDK */
|
||||
zegoExpressEngine.destroyEngine(null);
|
||||
zegoExpressEngine = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 zego SDK 的方法初始化。
|
||||
*/
|
||||
public void zegoInitializeEngine(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
|
||||
try {
|
||||
String zego_id = mActivity.getResources().getString(R.string.zego_appID);
|
||||
Log.d(TAG, "zegoInitializeEngine: => " + zego_id);
|
||||
|
||||
ZegoEngineConfig engineConfig = new ZegoEngineConfig();
|
||||
engineConfig.advancedConfig.put("audio_device_mode", "1");
|
||||
ZegoExpressEngine.setEngineConfig(engineConfig);
|
||||
|
||||
ZegoEngineProfile profile = new ZegoEngineProfile();
|
||||
/** 请通过官网注册获取,格式为 123456789L */
|
||||
profile.appID = Long.parseLong(zego_id.replace("zego_", ""));//mActivity.getResources().getInteger(R.integer.zego_appID);
|
||||
/** 64个字符,请通过官网注册获取,格式为"0123456789012345678901234567890123456789012345678901234567890123" */
|
||||
profile.appSign = mActivity.getString(R.string.zego_appSign).replace("zego_", "");
|
||||
/** 通用场景接入 */
|
||||
profile.scenario = ZegoScenario.STANDARD_CHATROOM;//;
|
||||
/** 设置app的application 对象 */
|
||||
profile.application = mActivity.getApplication();
|
||||
/** 创建引擎 */
|
||||
zegoExpressEngine = ZegoExpressEngine.createEngine(profile, zegoEventHandler);
|
||||
|
||||
zegoLogin(nAppActivity, _context);
|
||||
zegoLoginOut(nAppActivity, _context);
|
||||
zegoStartPublishingStream(nAppActivity, _context);
|
||||
zegoStopPublishingStream(nAppActivity, _context);
|
||||
zegoMuteAllPlayStreamAudio(nAppActivity, _context);
|
||||
zegoStartPlayingStream(nAppActivity, _context);
|
||||
zegoStopPlayingStream(nAppActivity, _context);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "zegoInitializeEngine: error=> " + Log.getStackTraceString(e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入频道:供LUA调用
|
||||
*/
|
||||
public void zegoLogin(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_Login, arg -> {
|
||||
try {
|
||||
Log.d(TAG, "zegoLogin: " + arg);
|
||||
ZegoJoinJsonStr = arg;
|
||||
|
||||
Message msg = new Message();
|
||||
msg.what = nAppActivity.HANDLER_ZEGOLOGIN;
|
||||
msg.obj = arg;
|
||||
nAppActivity.handler.sendMessage(msg);
|
||||
|
||||
} catch (Exception exception) {
|
||||
Log.d(TAG, "zegoLogin:=>error " + exception.toString());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入频道:供LUA调用
|
||||
*/
|
||||
public void zegoLoginFun(AppActivity nAppActivity, Context _context, String param) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
try {
|
||||
Log.d(TAG, "zegoLoginFun: " + param);
|
||||
|
||||
JSONObject jo = new JSONObject(param);
|
||||
String userId = jo.getString("userId");
|
||||
String roomId = jo.getString("roomId");
|
||||
|
||||
/** 创建用户 */
|
||||
ZegoUser user = new ZegoUser(userId);
|
||||
/** 开始登陆房间 */
|
||||
zegoExpressEngine.loginRoom(roomId, user);
|
||||
zegoExpressEngine.startPublishingStream(userId);
|
||||
zegoExpressEngine.startSoundLevelMonitor(200);//启动声浪监控
|
||||
isClosePublishingStream = false;
|
||||
|
||||
String reStr = "0";
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_Login, reStr);
|
||||
} catch (Exception exception) {
|
||||
Log.d(TAG, "zegoLoginFun:=>error " + exception.toString());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 离开频道:供LUA调用
|
||||
*/
|
||||
public void zegoLoginOut(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_LoginOut, arg -> {
|
||||
try {
|
||||
CloseZegoStreamList.clear();
|
||||
zegoExpressEngine.logoutRoom();
|
||||
} catch (Exception exception) {
|
||||
Log.d(TAG, "zegoLoginOut: =>error " + exception.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消或恢复发布本地音频流:供LUA调用 - 推流
|
||||
*/
|
||||
public void zegoStartPublishingStream(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_StartPublish, strParam -> {
|
||||
try {
|
||||
Log.i(TAG, "zegoStartPublishingStream:=>strParam " + strParam);
|
||||
|
||||
JSONObject jo = new JSONObject(strParam);
|
||||
String streamId = jo.getString("streamId");
|
||||
isClosePublishingStream = false;
|
||||
zegoExpressEngine.startPublishingStream(streamId);
|
||||
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_StartPublish, "0|false");
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "zegoStartPublishingStream: =>error " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消或恢复发布本地音频流:供LUA调用 - 停推流
|
||||
*/
|
||||
public void zegoStopPublishingStream(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_StopPublish, strParam -> {
|
||||
try {
|
||||
Log.i(TAG, "zegoStopPublishingStream:=>strParam " + strParam);
|
||||
isClosePublishingStream = true;
|
||||
zegoExpressEngine.stopPublishingStream();
|
||||
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_StopPublish, "0|true");
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "zegoStopPublishingStream: =>error " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消或恢复订阅所有远端用户的音频流:供LUA调用
|
||||
*/
|
||||
public void zegoMuteAllPlayStreamAudio(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_AllPlay, muteBean -> {
|
||||
try {
|
||||
Log.i(TAG, "zegoMuteAllPlayStreamAudio:=>strParam " + muteBean);
|
||||
|
||||
JSONObject jo = new JSONObject(muteBean);
|
||||
boolean muted = jo.getBoolean("muted");
|
||||
|
||||
zegoExpressEngine.muteAllPlayStreamAudio(muted);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "zegoMuteAllPlayStreamAudio: =>error " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消或恢复订阅指定远端用户的音频流:供LUA调用 - 拉流
|
||||
*/
|
||||
public void zegoStartPlayingStream(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_StartPlay, muteBean -> {
|
||||
try {
|
||||
Log.i(TAG, "zegoStartPlayingStream:=>strParam " + muteBean);
|
||||
|
||||
JSONObject jo = new JSONObject(muteBean);
|
||||
String streamId = jo.getString("streamId");
|
||||
|
||||
if (CloseZegoStreamList.contains(streamId))
|
||||
CloseZegoStreamList.remove(streamId);
|
||||
|
||||
zegoExpressEngine.startPlayingStream(streamId);
|
||||
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_StartPlay, "0|" + streamId + "|false");
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "zegoStartPlayingStream: =>error " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消或恢复订阅指定远端用户的音频流:供LUA调用 - 停拉流
|
||||
*/
|
||||
public void zegoStopPlayingStream(AppActivity nAppActivity, Context _context) {
|
||||
InitInfo(nAppActivity, _context);
|
||||
GetJsbBridgeWrapper().addScriptEventListener(EventNameUtil.Zg_StopPlay, muteBean -> {
|
||||
try {
|
||||
Log.i(TAG, "zegoStartPlayingStream:=>strParam " + muteBean);
|
||||
|
||||
JSONObject jo = new JSONObject(muteBean);
|
||||
String streamId = jo.getString("streamId");
|
||||
if (!CloseZegoStreamList.contains(streamId))
|
||||
CloseZegoStreamList.add(streamId);
|
||||
|
||||
zegoExpressEngine.stopPlayingStream(streamId);
|
||||
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_StopPlay, "0|" + streamId + "|true");
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "zegoStartPlayingStream: =>error " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有语音权限
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
public boolean checkAudioSelfPermission() {
|
||||
return mActivity.getApplicationContext().checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
private final IZegoEventHandler zegoEventHandler = new IZegoEventHandler() {
|
||||
/** 房间状态更新回调 */
|
||||
@Override
|
||||
public void onRoomStateChanged(String roomID, ZegoRoomStateChangedReason reason, int errorCode, JSONObject extendedData) {
|
||||
super.onRoomStateChanged(roomID, reason, errorCode, extendedData);
|
||||
Log.i(TAG, "onRoomStatZg_LogineUpdate: 🚩 🚪 Login room reason " + reason + " roomID:" + roomID + " errorCode:" + errorCode);
|
||||
if (reason == ZegoRoomStateChangedReason.LOGINING) {
|
||||
// 登录中
|
||||
Log.i(TAG, "onRoomStateChanged: 登录中");
|
||||
} else if (reason == ZegoRoomStateChangedReason.LOGINED) {
|
||||
// 登录成功
|
||||
//只有当房间状态是登录成功或重连成功时,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收发音视频
|
||||
//将自己的音视频流推送到 ZEGO 音视频云
|
||||
Log.i(TAG, "onRoomStateChanged: 登录成功");
|
||||
} else if (reason == ZegoRoomStateChangedReason.LOGIN_FAILED) {
|
||||
// 登录失败
|
||||
Log.i(TAG, "onRoomStateChanged: 登录失败");
|
||||
} else if (reason == ZegoRoomStateChangedReason.RECONNECTING) {
|
||||
// 重连中
|
||||
Log.i(TAG, "onRoomStateChanged: 重连中");
|
||||
} else if (reason == ZegoRoomStateChangedReason.RECONNECTED) {
|
||||
// 重连成功
|
||||
Log.i(TAG, "onRoomStateChanged: 重连成功");
|
||||
} else if (reason == ZegoRoomStateChangedReason.RECONNECT_FAILED) {
|
||||
// 重连失败
|
||||
Log.i(TAG, "onRoomStateChanged: 重连失败");
|
||||
} else if (reason == ZegoRoomStateChangedReason.KICK_OUT) {
|
||||
// 被踢出房间
|
||||
Log.i(TAG, "onRoomStateChanged: 被踢出房间");
|
||||
} else if (reason == ZegoRoomStateChangedReason.LOGOUT) {
|
||||
// 登出成功
|
||||
Log.i(TAG, "onRoomStateChanged: 登出成功");
|
||||
} else if (reason == ZegoRoomStateChangedReason.LOGOUT_FAILED) {
|
||||
// 登出失败
|
||||
Log.i(TAG, "onRoomStateChanged: 登出失败");
|
||||
}
|
||||
}
|
||||
// /** 房间状态更新回调 */
|
||||
// @Override
|
||||
// public void onRoomStateUpdate(String roomID, ZegoRoomState state, int errorCode, JSONObject extendedData) {
|
||||
// /** 根据需要实现事件回调 */
|
||||
// if (state == ZegoRoomState.CONNECTED && errorCode == 0) {
|
||||
// Log.i(TAG, "onRoomStatZg_LogineUpdate: 🚩 🚪 Login room success");
|
||||
// }
|
||||
// if (errorCode != 0) {
|
||||
// Log.i(TAG, "onRoomStateUpdate: 🚩 ❌ 🚪 Login room fail, errorCode: " + errorCode);
|
||||
// }
|
||||
// }
|
||||
|
||||
/** 用户状态更新 */
|
||||
@Override
|
||||
public void onRoomUserUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoUser> userList) {
|
||||
super.onRoomUserUpdate(roomID, updateType, userList);
|
||||
/** 根据需要实现事件回调 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 流状态更新
|
||||
*/
|
||||
@Override
|
||||
public void onRoomStreamUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoStream> streamList, JSONObject extendedData) {
|
||||
/** 根据需要实现事件回调 */
|
||||
super.onRoomStreamUpdate(roomID, updateType, streamList, extendedData);
|
||||
// Log.i(Zego_TAG, "🚩 🌊 onRoomStreamUpdate: roomID" + roomID + ", updateType:" + updateType.value() + ", streamList: " + streamList);
|
||||
|
||||
// Add the rendered view dynamically after pulling the stream here
|
||||
if (updateType == ZegoUpdateType.ADD) {
|
||||
for (ZegoStream zegoStream : streamList) {
|
||||
if (!ZegoStreamList.contains(zegoStream)) {
|
||||
ZegoStreamList.add(zegoStream);
|
||||
}
|
||||
|
||||
if (!CloseZegoStreamList.contains(zegoStream.streamID))
|
||||
ZegoExpressEngine.getEngine().startPlayingStream(zegoStream.streamID);
|
||||
}
|
||||
} else if (updateType == ZegoUpdateType.DELETE) {
|
||||
for (ZegoStream zegoStream : streamList) {
|
||||
if (ZegoStreamList.contains(zegoStream)) {
|
||||
ZegoStreamList.remove(zegoStream);
|
||||
}
|
||||
|
||||
ZegoExpressEngine.getEngine().stopPlayingStream(zegoStream.streamID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 推流状态更新回调*/
|
||||
@Override
|
||||
public void onPublisherStateUpdate(String streamID, ZegoPublisherState state, int errorCode, JSONObject extendedData) {
|
||||
// Log.i(Zego_TAG, "onPublisherStateUpdate streamID:"+streamID+" state:"+state);
|
||||
if (state == ZegoPublisherState.PUBLISHING && errorCode == 0) {
|
||||
Log.i(TAG, "onPublisherStateUpdate:🚩 📤 Publishing stream success");
|
||||
}
|
||||
if (errorCode != 0) {
|
||||
Log.i(TAG, "onPublisherStateUpdate: 🚩 ❌ 📤 Publishing stream fail, errorCode: " + errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
/** 拉流状态更新回调*/
|
||||
@Override
|
||||
public void onPlayerStateUpdate(String streamID, ZegoPlayerState state, int errorCode, JSONObject extendedData) {
|
||||
// Log.i(Zego_TAG, "onPlayerStateUpdate streamID:"+streamID+" state:"+state);
|
||||
if (state == ZegoPlayerState.PLAYING && errorCode == 0) {
|
||||
Log.i(TAG, "onPlayerStateUpdate: 🚩 📥 Playing stream success");
|
||||
}
|
||||
if (errorCode != 0) {
|
||||
Log.i(TAG, "onPlayerStateUpdate: 🚩 ❌ 📥 Playing stream fail, errorCode: " + errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
/** 接收远端拉流音频声浪回调 */
|
||||
@Override
|
||||
public void onRemoteSoundLevelUpdate(HashMap<String, Float> soundLevels) {
|
||||
super.onRemoteSoundLevelUpdate(soundLevels);
|
||||
// Log.i(Zego_TAG, "onRemoteSoundLevelUpdate:"+ soundLevels.size());
|
||||
for (HashMap.Entry<String, Float> entry : soundLevels.entrySet()) {
|
||||
String streamid = entry.getKey();
|
||||
Float value = entry.getValue();
|
||||
if (value > 10 && !streamid.equals("")) {
|
||||
String speakers_str = streamid + "|" + value;
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_AudioVolume, speakers_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 本地采集音频声浪回调 */
|
||||
@Override
|
||||
public void onCapturedSoundLevelUpdate(float soundLevel) {
|
||||
super.onCapturedSoundLevelUpdate(soundLevel);
|
||||
// Log.v(TAG, "onCapturedSoundLevelUpdate:" + soundLevel);
|
||||
if (!isClosePublishingStream && soundLevel > 10) {
|
||||
String speakers_str = "0|" + soundLevel;
|
||||
EventToScriptUtil.getInstance().dispatchEventToScript(EventNameUtil.Zg_AudioVolume, speakers_str);
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onCapturedSoundLevelInfoUpdate(ZegoSoundLevelInfo soundLevelInfo) {
|
||||
// super.onCapturedSoundLevelInfoUpdate(soundLevelInfo);
|
||||
// Log.v("ZegoAudioTalk", "onCapturedSoundLevelUpdate:" + soundLevelInfo.soundLevel);
|
||||
//// if(soundLevelInfo.soundLevel > 0 && soundLevelInfo.vad == 1){
|
||||
////
|
||||
//// }
|
||||
// final String speakers_str = "0|" + soundLevelInfo.soundLevel;
|
||||
// nAppActivity.runOnGLThread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// // 用户的音量 > 0 回调到lua 对应的玩家显示正在说话的状态
|
||||
// Cocos2dxLuaJavaBridge.callLuaGlobalFunctionWithString(
|
||||
// "Zego_OnAudioVolume", speakers_str + "");
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
};
|
||||
}
|
||||
@@ -17,6 +17,7 @@ buildscript {
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven { url 'https://storage.zego.im/maven' }
|
||||
google()
|
||||
mavenCentral()
|
||||
// jcenter() // keeped as anchor, will be removed soon
|
||||
|
||||
5
android/res/drawable/ps_image_placeholder.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#CCCCCC" />
|
||||
</shape>
|
||||
BIN
android/res/drawable/ps_permission.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
android/res/drawable/splash.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 64 KiB |
5
android/res/values/colors.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ps_color_grey">#666666</color>
|
||||
<color name="ps_color_white">#FFFFFF</color>
|
||||
</resources>
|
||||
7
android/res/values/ids.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources>
|
||||
<!--google play game service client id-->
|
||||
<string name="app_id" translatable="false">77777777777</string>
|
||||
<!--PictureSelector-->
|
||||
<item name="title_bar" type="id"/>
|
||||
</resources>
|
||||
@@ -1,2 +1,18 @@
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">101 Okey Neşeli</string>
|
||||
<!--google start-->
|
||||
<!--google sign in -->
|
||||
<!--google play game service sign -->
|
||||
<string name="google_client_id" translatable="false">77777777777-pe7pidhpuc9ohkg5t8aqip7qboire346.apps.googleusercontent.com</string>
|
||||
<!--google end-->
|
||||
<!--Adjust-->
|
||||
<string name="Adjust_AppToken" translatable="false">4fbx099pwqv4</string>
|
||||
<!--Bugly-->
|
||||
<string name="Tely_AppId" translatable="false">63f5a8b9d4</string>
|
||||
<string name="Tely_Version" translatable="false">1.0.0</string>
|
||||
<string name="Tely_Channel" translatable="false">happyokey</string>
|
||||
<bool name="Tely_IsDebug" translatable="false">false</bool>
|
||||
<!--zego-->
|
||||
<string name="zego_appID" translatable="false">zego_57566727</string>
|
||||
<string name="zego_appSign" translatable="false">zego_e7e8723ad58492924c5c26087f735ee2f8b748cbd30acff1194ef1b37810f389</string>
|
||||
</resources>
|
||||
|
||||