This commit is contained in:
puxuan 2025-08-05 17:29:22 +08:00
parent 6ef7de12af
commit eb10c29940
73 changed files with 6533 additions and 3508 deletions

View File

@ -18,7 +18,7 @@ namespace BFEditor.Build
private static int VersionCodeRU = 12;
private static string VersionNameRU = "0.4.9";
BFPlatformOptions platform = BFPlatformOptions.AndroidDev;
const string ANDROID_GP_PACKAGE_NAME = "com.c1.dev.android";
const string ANDROID_GP_PACKAGE_NAME = "com.fortune.td.game.global";
public BuildProjectWindow()
{

View File

@ -42,7 +42,7 @@ namespace BF
// 渠道对应的语言配置
public static Dictionary<string, BFLanguageInfo> languageInfos = new Dictionary<string, BFLanguageInfo>()
{
{"com.c1.dev.android", new BFLanguageInfo(new List<string>{"en", "cn", "zh", "th", "ru", "id", "vi"})},
{"com.fortune.td.game.global", new BFLanguageInfo(new List<string>{"en", "cn", "zh", "th", "ru", "id", "vi"})},
{"com.juzu.b6.dev.android", new BFLanguageInfo(new List<string>{"en", "cn", "zh", "th", "ru", "id", "vi"})},
{"com.juzu.b6.dev.ios", new BFLanguageInfo(new List<string>{"en", "cn"})},
{"com.juzu.b6.release.android", new BFLanguageInfo(new List<string>{"en"})},

80
BFVersions/android/dz_dev/build.gradle Normal file → Executable file
View File

@ -1,40 +1,40 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
// classpath 'com.google.gms:google-services:4.3.13'
// classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.google.gms:google-services:4.3.13'
// classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

10
BFVersions/android/dz_dev/gradle.properties Normal file → Executable file
View File

@ -1,6 +1,6 @@
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
unityStreamingAssets=.unity3d, .bytes, .ab

216
BFVersions/android/dz_dev/unityLibrary/build.gradle Normal file → Executable file
View File

@ -1,119 +1,97 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
// Android Resolver Repos Start
([rootProject] + (rootProject.subprojects as List)).each { project ->
project.repositories {
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
maven {
url "https://maven.google.com"
}
maven {
url "https://android-sdk.is.com/" // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:9, Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:16, Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:16, Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:8, Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:8, Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:16, Assets/IronSource/Editor/ISLiftoffAdapterDependencies.xml:16, Assets/IronSource/Editor/ISPangleAdapterDependencies.xml:8, Assets/IronSource/Editor/ISTapJoyAdapterDependencies.xml:8, Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:8
}
maven {
url "https://maven.google.com/" // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:17, Assets/IronSource/Editor/IronSourceSDKDependencies.xml:25, Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:8, Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:8, Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:15, Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:15, Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:8, Assets/IronSource/Editor/ISLiftoffAdapterDependencies.xml:8, Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:15
}
maven {
url "https://artifact.bytedance.com/repository/pangle/" // Assets/IronSource/Editor/ISPangleAdapterDependencies.xml:15
}
maven {
url "https://sdk.tapjoy.com/" // Assets/IronSource/Editor/ISTapJoyAdapterDependencies.xml:15
}
mavenLocal()
jcenter()
mavenCentral()
}
}
// Android Resolver Repos End
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:multidex:1.0.3'
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation(name: 'facebook-android-wrapper-11.0.0', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:5.0.0"
// firebase
// implementation 'com.google.firebase:firebase-analytics:21.1.0'
// implementation 'com.google.firebase:firebase-crashlytics:18.2.12'
// implementation 'com.google.firebase:firebase-messaging:23.0.8'
// Android Resolver Dependencies Start
implementation 'com.adcolony:sdk:4.8.0' // Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:8
implementation 'com.android.installreferrer:installreferrer:2.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:10
implementation 'com.android.support:appcompat-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:cardview-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:customtabs:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:support-v4:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.applovin:applovin-sdk:11.7.1' // Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:15
implementation 'com.appsflyer:af-android-sdk:6.4.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:6
implementation 'com.appsflyer:unity-wrapper:6.4.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:8
implementation 'com.chartboost:chartboost-sdk:9.2.0' // Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:15
implementation 'com.facebook.android:audience-network-sdk:6.12.0' // Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:8
implementation 'com.facebook.android:facebook-applinks:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:6
implementation 'com.facebook.android:facebook-core:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:5
implementation 'com.facebook.android:facebook-gamingservices:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:9
implementation 'com.facebook.android:facebook-login:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:7
implementation 'com.facebook.android:facebook-share:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:8
implementation 'com.google.android.gms:play-services-ads:21.5.0' // Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:8
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:17
implementation 'com.google.android.gms:play-services-basement:18.1.0' // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:25
implementation 'com.ironsource.adapters:adcolonyadapter:4.3.14' // Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:admobadapter:4.3.35' // Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:applovinadapter:4.3.37' // Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:chartboostadapter:4.3.11' // Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:facebookadapter:4.3.39' // Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:liftoffadapter:4.3.5' // Assets/IronSource/Editor/ISLiftoffAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:pangleadapter:4.3.17' // Assets/IronSource/Editor/ISPangleAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:tapjoyadapter:4.1.24' // Assets/IronSource/Editor/ISTapJoyAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:unityadsadapter:4.3.26' // Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:8
implementation 'com.ironsource.sdk:mediationsdk:7.3.0' // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:9
implementation 'com.pangle.global:ads-sdk:5.0.0.8' // Assets/IronSource/Editor/ISPangleAdapterDependencies.xml:15
implementation 'com.parse.bolts:bolts-android:1.4.0' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:4
implementation 'com.tapjoy:tapjoy-android-sdk:12.11.1' // Assets/IronSource/Editor/ISTapJoyAdapterDependencies.xml:15
implementation 'com.unity3d.ads:unity-ads:4.6.0' // Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:15
implementation 'io.liftoff:liftoffads:1.9.1' // Assets/IronSource/Editor/ISLiftoffAdapterDependencies.xml:8
// Android Resolver Dependencies End
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
ndk {
abiFilters 'armeabi-v7a'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
}
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
// Android Resolver Repos Start
([rootProject] + (rootProject.subprojects as List)).each { project ->
project.repositories {
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
maven {
url "https://maven.google.com"
}
maven {
url "https://android-sdk.is.com/" // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:9, Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:16, Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:8, Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:16, Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:8
}
maven {
url "https://maven.google.com/" // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:17, Assets/IronSource/Editor/IronSourceSDKDependencies.xml:25, Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:8, Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:15, Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:8, Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:15
}
mavenLocal()
jcenter()
mavenCentral()
}
}
// Android Resolver Repos End
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:multidex:1.0.3'
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation(name: 'facebook-android-wrapper-11.0.0', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:5.0.0"
// Android Resolver Dependencies Start
implementation 'com.android.installreferrer:installreferrer:2.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:10
implementation 'com.android.support:appcompat-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:cardview-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:customtabs:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:support-v4:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.applovin:applovin-sdk:11.5.5' // Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:15
implementation 'com.appsflyer:af-android-sdk:6.4.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:6
implementation 'com.appsflyer:unity-wrapper:6.4.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:8
implementation 'com.facebook.android:audience-network-sdk:6.12.0' // Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:8
implementation 'com.facebook.android:facebook-applinks:[11.0, 12)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:6
implementation 'com.facebook.android:facebook-core:[11.0, 12)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:5
implementation 'com.facebook.android:facebook-gamingservices:[11.0, 12)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:9
implementation 'com.facebook.android:facebook-login:[11.0, 12)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:7
implementation 'com.facebook.android:facebook-share:[11.0, 12)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:8
implementation 'com.google.android.gms:play-services-ads:21.3.0' // Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:8
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:17
implementation 'com.google.android.gms:play-services-basement:18.1.0' // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:25
implementation 'com.ironsource.adapters:admobadapter:4.3.33' // Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:applovinadapter:4.3.35' // Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:facebookadapter:4.3.38' // Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:unityadsadapter:4.3.24' // Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:8
implementation 'com.ironsource.sdk:mediationsdk:7.2.6' // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:9
implementation 'com.parse.bolts:bolts-android:1.4.0' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:4
implementation 'com.unity3d.ads:unity-ads:4.4.1' // Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:15
// Android Resolver Dependencies End
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
ndk {
abiFilters 'armeabi-v7a'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
}
}

View File

@ -1,66 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<!-- [START firebase_service] -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/firebase_icon" />
<service
android:name="com.juzu.dz.third.BFFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8252390069143459~7841203986"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
android:value="true"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
android:value="true"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<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.WAKE_LOCK”"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<!-- [START firebase_service] -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/firebase_icon" />
<service
android:name="com.juzu.dz.third.BFFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-1136292565368915~8864142088"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
</manifest>

View File

@ -1,188 +1,177 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import android.os.Build;
// import com.chartboost.sdk.Chartboost;
import com.juzu.dz.third.GooglePlugin;
import com.ironsource.mediationsdk.IronSource;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
IronSource.onPause(this);
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
IronSource.onResume(this);
}
@Override
public void onBackPressed() {
// If an interstitial is on screen, close it.
// if (Chartboost.onBackPressed()) {
// return;
// } else {
// super.onBackPressed();
// }
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import com.chartboost.sdk.Chartboost;
import com.juzu.dz.third.GooglePlugin;
// import com.ironsource.mediationsdk.IronSource;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
// IronSource.onPause(this);
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
// IronSource.onResume(this);
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>

74
BFVersions/android/dz_google_abb/build.gradle Normal file → Executable file
View File

@ -1,37 +1,37 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

10
BFVersions/android/dz_google_abb/gradle.properties Normal file → Executable file
View File

@ -1,6 +1,6 @@
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
unityStreamingAssets=.unity3d, .bytes, .ab

View File

@ -1,7 +1,7 @@
apply plugin: 'com.android.asset-pack'
assetPack{
packName = "install_time_pack"
dynamicDelivery {
deliveryType = "install-time"
}
apply plugin: 'com.android.asset-pack'
assetPack{
packName = "install_time_pack"
dynamicDelivery {
deliveryType = "install-time"
}
}

148
BFVersions/android/dz_google_abb/launcher/build.gradle Normal file → Executable file
View File

@ -1,74 +1,74 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.application'
dependencies {
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation project(':unityLibrary')
implementation 'com.google.android.play:core:1.10.0'
}
android {
assetPacks = [":install_time_pack"]
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
applicationId 'com.idlelegend.arenaclash.battlefire'
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
versionCode 1
versionName '0.1.0'
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
lintOptions {
abortOnError false
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
jniDebuggable true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
}
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
doNotStrip '*/x86/*.so'
doNotStrip '*/x86_64/*.so'
}
bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = true
}
}
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.application'
dependencies {
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation project(':unityLibrary')
implementation 'com.google.android.play:core:1.10.0'
}
android {
assetPacks = [":install_time_pack"]
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
applicationId 'com.idlelegend.arenaclash.battlefire'
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
versionCode 1
versionName '0.1.0'
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
lintOptions {
abortOnError false
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
jniDebuggable true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
}
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
doNotStrip '*/x86/*.so'
doNotStrip '*/x86_64/*.so'
}
bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = true
}
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.idlelegend.arenaclash.battlefire" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:extractNativeLibs="true" android:label="@string/app_name" android:icon="@mipmap/app_icon" android:roundIcon="@mipmap/app_icon_round" >
</application>
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.idlelegend.arenaclash.battlefire" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:extractNativeLibs="true" android:label="@string/app_name" android:icon="@mipmap/app_icon" android:roundIcon="@mipmap/app_icon_round" >
</application>
</manifest>

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,125 +1,125 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation(name: 'androidx.activity.activity-1.0.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-1.1.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-resources-1.1.0', ext:'aar')
implementation(name: 'androidx.browser.browser-1.0.0', ext:'aar')
implementation(name: 'androidx.cardview.cardview-1.0.0', ext:'aar')
implementation(name: 'androidx.core.core-ktx-1.3.2', ext:'aar')
implementation(name: 'androidx.legacy.legacy-support-v4-1.0.0', ext:'aar')
implementation(name: 'androidx.media.media-1.0.0', ext:'aar')
implementation(name: 'androidx.savedstate.savedstate-1.0.0', ext:'aar')
implementation(name: 'androidx.vectordrawable.vectordrawable-animated-1.1.0', ext:'aar')
implementation(name: 'com.android.installreferrer.installreferrer-2.1', ext:'aar')
implementation(name: 'com.appsflyer.af-android-sdk-6.4.1', ext:'aar')
implementation(name: 'com.appsflyer.oaid-6.2.4', ext:'aar')
implementation(name: 'com.appsflyer.unity-wrapper-6.4.1', ext:'aar')
implementation(name: 'com.facebook.android.facebook-applinks-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-common-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-core-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-gamingservices-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-login-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-share-11.3.0', ext:'aar')
implementation(name: 'facebook-android-wrapper-11.0.0', ext:'aar')
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:5.0.0"
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation 'com.google.firebase:firebase-analytics:21.1.0'
implementation 'com.google.firebase:firebase-messaging'
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
doNotStrip '*/x86/*.so'
doNotStrip '*/x86_64/*.so'
}
}
def getSdkDir() {
Properties local = new Properties()
local.load(new FileInputStream("${rootDir}/local.properties"))
return local.getProperty('sdk.dir')
}
def BuildIl2Cpp(String workingDir, String targetDirectory, String architecture, String abi, String configuration) {
exec {
commandLine(workingDir + "/src/main/Il2CppOutputProject/IL2CPP/build/deploy/netcoreapp3.1/il2cpp",
"--compile-cpp",
"--libil2cpp-static",
"--platform=Android",
"--architecture=" + architecture,
"--configuration=" + configuration,
"--outputpath=" + workingDir + targetDirectory + abi + "/libil2cpp.so",
"--cachedirectory=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_cache",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/external/bdwgc/include",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/libil2cpp/include",
"--tool-chain-path=" + android.ndkDirectory,
"--map-file-parser=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/MapFileParser/MapFileParser.exe",
"--generatedcppdir=" + workingDir + "/src/main/Il2CppOutputProject/Source/il2cppOutput",
"--baselib-directory=" + workingDir + "/src/main/jniStaticLibs/" + abi,
"--dotnetprofile=unityaot")
environment "ANDROID_SDK_ROOT", getSdkDir()
}
delete workingDir + targetDirectory + abi + "/libil2cpp.sym.so"
ant.move(file: workingDir + targetDirectory + abi + "/libil2cpp.dbg.so", tofile: workingDir + "/symbols/" + abi + "/libil2cpp.so")
}
android {
task BuildIl2CppTask {
doLast {
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARMv7', 'armeabi-v7a', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARM64', 'arm64-v8a', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'x86', 'x86', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'x64', 'x86_64', 'Release');
}
}
afterEvaluate {
if (project(':unityLibrary').tasks.findByName('mergeDebugJniLibFolders'))
project(':unityLibrary').mergeDebugJniLibFolders.dependsOn BuildIl2CppTask
if (project(':unityLibrary').tasks.findByName('mergeReleaseJniLibFolders'))
project(':unityLibrary').mergeReleaseJniLibFolders.dependsOn BuildIl2CppTask
}
sourceSets {
main {
jni.srcDirs = ["src/main/Il2CppOutputProject"]
}
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation(name: 'androidx.activity.activity-1.0.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-1.1.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-resources-1.1.0', ext:'aar')
implementation(name: 'androidx.browser.browser-1.0.0', ext:'aar')
implementation(name: 'androidx.cardview.cardview-1.0.0', ext:'aar')
implementation(name: 'androidx.core.core-ktx-1.3.2', ext:'aar')
implementation(name: 'androidx.legacy.legacy-support-v4-1.0.0', ext:'aar')
implementation(name: 'androidx.media.media-1.0.0', ext:'aar')
implementation(name: 'androidx.savedstate.savedstate-1.0.0', ext:'aar')
implementation(name: 'androidx.vectordrawable.vectordrawable-animated-1.1.0', ext:'aar')
implementation(name: 'com.android.installreferrer.installreferrer-2.1', ext:'aar')
implementation(name: 'com.appsflyer.af-android-sdk-6.4.1', ext:'aar')
implementation(name: 'com.appsflyer.oaid-6.2.4', ext:'aar')
implementation(name: 'com.appsflyer.unity-wrapper-6.4.1', ext:'aar')
implementation(name: 'com.facebook.android.facebook-applinks-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-common-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-core-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-gamingservices-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-login-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-share-11.3.0', ext:'aar')
implementation(name: 'facebook-android-wrapper-11.0.0', ext:'aar')
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:4.0.0"
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation 'com.google.firebase:firebase-analytics:21.1.0'
implementation 'com.google.firebase:firebase-messaging'
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
doNotStrip '*/x86/*.so'
doNotStrip '*/x86_64/*.so'
}
}
def getSdkDir() {
Properties local = new Properties()
local.load(new FileInputStream("${rootDir}/local.properties"))
return local.getProperty('sdk.dir')
}
def BuildIl2Cpp(String workingDir, String targetDirectory, String architecture, String abi, String configuration) {
exec {
commandLine(workingDir + "/src/main/Il2CppOutputProject/IL2CPP/build/deploy/netcoreapp3.1/il2cpp",
"--compile-cpp",
"--libil2cpp-static",
"--platform=Android",
"--architecture=" + architecture,
"--configuration=" + configuration,
"--outputpath=" + workingDir + targetDirectory + abi + "/libil2cpp.so",
"--cachedirectory=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_cache",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/external/bdwgc/include",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/libil2cpp/include",
"--tool-chain-path=" + android.ndkDirectory,
"--map-file-parser=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/MapFileParser/MapFileParser.exe",
"--generatedcppdir=" + workingDir + "/src/main/Il2CppOutputProject/Source/il2cppOutput",
"--baselib-directory=" + workingDir + "/src/main/jniStaticLibs/" + abi,
"--dotnetprofile=unityaot")
environment "ANDROID_SDK_ROOT", getSdkDir()
}
delete workingDir + targetDirectory + abi + "/libil2cpp.sym.so"
ant.move(file: workingDir + targetDirectory + abi + "/libil2cpp.dbg.so", tofile: workingDir + "/symbols/" + abi + "/libil2cpp.so")
}
android {
task BuildIl2CppTask {
doLast {
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARMv7', 'armeabi-v7a', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARM64', 'arm64-v8a', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'x86', 'x86', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'x64', 'x86_64', 'Release');
}
}
afterEvaluate {
if (project(':unityLibrary').tasks.findByName('mergeDebugJniLibFolders'))
project(':unityLibrary').mergeDebugJniLibFolders.dependsOn BuildIl2CppTask
if (project(':unityLibrary').tasks.findByName('mergeReleaseJniLibFolders'))
project(':unityLibrary').mergeReleaseJniLibFolders.dependsOn BuildIl2CppTask
}
sourceSets {
main {
jni.srcDirs = ["src/main/Il2CppOutputProject"]
}
}
}

View File

@ -1,67 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<activity android:name="com.facebook.unity.FBUnityLoginActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityDialogsActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityGamingServicesFriendFinderActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityAppLinkActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityDeepLinkingActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityGameRequestActivity" />
<activity android:name="com.facebook.unity.FBUnityCreateGameGroupActivity" />
<activity android:name="com.facebook.unity.FBUnityJoinGameGroupActivity" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb277827051329111" />
<meta-data android:name="com.facebook.sdk.AutoLogAppEventsEnabled" android:value="true" />
<meta-data android:name="com.facebook.sdk.AdvertiserIDCollectionEnabled" android:value="true" />
<provider android:name="com.facebook.FacebookContentProvider" android:authorities="com.facebook.app.FacebookContentProvider277827051329111" android:exported="true" />
<!-- <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> -->
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8252390069143459~7841203986"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
android:value="true"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
android:value="true"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<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.WAKE_LOCK”"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<activity android:name="com.facebook.unity.FBUnityLoginActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityDialogsActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityGamingServicesFriendFinderActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityAppLinkActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityDeepLinkingActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityGameRequestActivity" />
<activity android:name="com.facebook.unity.FBUnityCreateGameGroupActivity" />
<activity android:name="com.facebook.unity.FBUnityJoinGameGroupActivity" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb491773936518549" />
<meta-data android:name="com.facebook.sdk.AutoLogAppEventsEnabled" android:value="true" />
<meta-data android:name="com.facebook.sdk.AdvertiserIDCollectionEnabled" android:value="true" />
<provider android:name="com.facebook.FacebookContentProvider" android:authorities="com.facebook.app.FacebookContentProvider491773936518549" android:exported="true" />
<!-- <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> -->
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-1136292565368915~8864142088"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
</manifest>

View File

@ -0,0 +1,30 @@
package com.juzu.dz.message;
/**
* 管理和前端的通信消息以及json字段
* */
public class BFMessage {
// Google登录
public static final int GOOGLE_LOGIN_SUCCESS = 1;
public static final int GOOGLE_LOGIN_FAILED = 2;
// Google登出成功
public static final int GOOGLE_LOGOUT_SUCCESS = 3;
// Google支付
public static final int GOOGLE_PAY_SUCCESS = 4;
public static final int GOOGLE_PAY_FAILED = 5;
public static final int GOOGLE_PAY_CANCEL = 6;
public static final int GOOGLE_CONNECT_SUCCESS = 7;
public static final int GOOGLE_CONNECT_FAILED = 8;
public static final int QUERY_PRODUCT_SUCCESS = 9;
public static final int QUERY_PRODUCT_FAILED = 10;
public static final int QUERY_UNCOMPLETE_ORDER_FINISH = 11;
// Google消耗
public static final int GOOGLE_CONSUME_SUCCESS = 12;
public static final int GOOGLE_CONSUME_FAILED = 13;
// Google登出失败
public static final int GOOGLE_LOGOUT_FAILED = 14;
// fireBaseToken
public static final int FIREBASE_TOKEN = 15;
// Google订阅
public static final int QUERY_SUBSCRIBE_FINISH = 16;
}

View File

@ -0,0 +1,459 @@
package com.juzu.dz.third;
import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.billingclient.api.AccountIdentifiers;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
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.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import com.juzu.dz.message.BFMessage;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GoogleBilling {
private static volatile GoogleBilling sInstance;
private static final String LOG_TAG = "GoogleBilling";
private static BillingClient mGoogleBillingClient;
private Map<String, Purchase> mPurchase = new HashMap<String, Purchase>();
private List<SkuDetails> mSubList = new ArrayList<SkuDetails>();
private List<SkuDetails> mInAppList = new ArrayList<SkuDetails>();
final private static String BASE_64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2Vcz26Jz82oYAkr8Wsk0z0hgwBLDRbmnQyARqusiSaJWOt9vEaTgLtLaWYYIiWIeWXUaKq35xDHjC5Xh+KI/pp5N7ck1yB5+lyaSsVD0ESFC/qjDWgElaxxL9QvOyLEHd23q9TmlF1aWziSc6ryFX9HVEGLJT2bTjVEz/bk/WpfN41HZafqQTCIWh8+vRgr0CXa/JEqysjDYRpbaBViPE9F7aTo8lCv/VQpE1ycFiOoaf768aispY5cXb0qP00li95HAI+fEaYgxOuRmN0oc5BFpNRNYTMmRX1Oi5F2vknw+u3+mh+a6GkbwD6FCK+fWIo8hZAWnkULgrxa1ReobQIDAQAB";
public static GoogleBilling getInstance()
{
if (sInstance == null) {
synchronized (GoogleBilling.class) {
if (sInstance == null) {
sInstance = new GoogleBilling();
}
}
}
return sInstance;
}
public void init(Activity activity){
mGoogleBillingClient = BillingClient.newBuilder(activity).setListener(payListener).enablePendingPurchases().build();
connectGoogleStore();
}
public void connectGoogleStore(){
mGoogleBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_SUCCESS, "");
}else{
String msg = billingResult.getDebugMessage();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, msg);
}
}
@Override
public void onBillingServiceDisconnected() {
String msg = "disconnected";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, msg);
}
});
}
// 查询商品信息本地化用
public void queryProductsInfo(String payType, String productInfoJson){
Log.d(LOG_TAG, "google queryProductsInfo info from unity:" + productInfoJson);
try {
JSONArray array = new JSONArray(productInfoJson);
String[] proList = new String[array.length()];
for (int i = 0; i < array.length(); i++){
proList[i] = (String)array.get(i);
}
queryProducts(payType, proList);
} catch (JSONException e) {
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, e.toString());
}
}
//通过商品id查询商品详情
private void queryProducts(String payType, String [] products){
List<String> pList = Arrays.asList(products);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(pList).setType(payType);
mGoogleBillingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> list) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null){
Log.d(LOG_TAG, "queryProducts success count:" + list.size());
if (list.size() == 0){
String msg = "未查询到商品信息,请检查传入的商品id,或者配置是否生效";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, msg);
return;
}
JSONArray array = new JSONArray();
List<SkuDetails> mList = new ArrayList<SkuDetails>();
for (SkuDetails skuDetails : list) {
mList.add(skuDetails);
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();//实际价格
String originPrice = skuDetails.getOriginalPrice();//原价如果没折扣原价=实际价格
String description = skuDetails.getDescription();
String originalJson = skuDetails.getOriginalJson();
String title = skuDetails.getTitle();
String priceAmountMicros = String.valueOf(skuDetails.getPriceAmountMicros());
String currencyCode = skuDetails.getPriceCurrencyCode();
JSONObject info = new JSONObject();
try {
info.put("sku", sku);
info.put("price", price);
info.put("originPrice", originPrice);
info.put("description", description);
info.put("originalJson", originalJson);
info.put("title", title);
info.put("priceCurrencyCode", currencyCode);
info.put("priceAmountMicros", priceAmountMicros);
} catch (JSONException e) {
e.printStackTrace();
}
array.put(info);
}
if(payType.equals(BillingClient.SkuType.INAPP)){
mInAppList = mList;
}
if(payType.equals(BillingClient.SkuType.SUBS)){
mSubList = mList;
}
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_SUCCESS, array.toString());
}else{
String msg = "queryProducts error:" + billingResult.getResponseCode();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, msg);
}
}
});
}
// 支付
public void pay(Activity activity, String payType, String productId, String customMsg){
List<SkuDetails> skuList = null;
if(payType.equals(BillingClient.SkuType.INAPP)){
skuList = mInAppList;
}
if(payType.equals(BillingClient.SkuType.SUBS)){
skuList = mSubList;
}
if (skuList == null || skuList.size() == 0){
String msg = "no sku";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
return ;
}
SkuDetails paySku = null;
for (SkuDetails details:skuList){
if (TextUtils.equals(productId, details.getSku())){
paySku = details;
break;
}
}
if (paySku == null){
String msg = "sku not found! please contact developer";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
return;
}
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(paySku)
.setObfuscatedAccountId(customMsg)
.build();
BillingResult result = mGoogleBillingClient.launchBillingFlow(activity, flowParams);
if (result.getResponseCode() != BillingClient.BillingResponseCode.OK){
String msg = "Billing failed: + " + result.getDebugMessage();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
}
private PurchasesUpdatedListener payListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
switch (billingResult.getResponseCode()) {
case BillingClient.BillingResponseCode.OK:
if (null != purchases) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else {
String msg = "Null Purchase List Returned from OK response!";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
break;
case BillingClient.BillingResponseCode.USER_CANCELED:
Log.i(LOG_TAG, "onPurchasesUpdated: User canceled the purchase");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_CANCEL, "");
break;
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
String msg = "onPurchasesUpdated: The user already owns this item";
Log.i(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
break;
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
String msg2 = "onPurchasesUpdated: 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.";
Log.e(LOG_TAG, msg2);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg2);
break;
default:
String msg3 = "BillingResult [" + billingResult.getResponseCode() + "]: " + billingResult.getDebugMessage();
Log.d(LOG_TAG, msg3);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg3);
}
}
};
private void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
// 支付完成
if(!purchase.isAcknowledged()){
mPurchase.put(purchase.getPurchaseToken(),purchase);
}
//验证签名
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
boolean succ = verifyValidSignature(originalJson, signature);
JSONObject productInfo = new JSONObject();
try {
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
productInfo.put("signtureFlag", succ + "");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_SUCCESS, productInfo.toString());
}else{
//未付款
String msg = "purchase.getPurchaseState() != Purchase.PurchaseState.PURCHASED";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
}
//消耗
public void consumeAsync(String purchaseToken){
Purchase purchase = mPurchase.get(purchaseToken);
boolean isSub = false;
if(purchase != null){
if(mSubList != null){
for(SkuDetails Sku:mSubList){
for ( String purchaseSku : purchase.getSkus() ) {
if (purchaseSku.equals(Sku.getSku())) {
isSub = true;
break;
}
}
}
}
}
if(isSub){
handleSubsPurchase(purchase);
}else{
final ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken)
.build();
mGoogleBillingClient.consumeAsync(consumeParams, (billingResult, purchaseToken1) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "消耗成功...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_SUCCESS, "");
} else {
Log.d(LOG_TAG, "消耗失败...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "");
}
});
}
}
private void handleSubsPurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken())
.build();
mGoogleBillingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {
@Override
public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "订阅成功...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_SUCCESS, "");
} else {
Log.d(LOG_TAG, "订阅失败...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "");
}
}
});
}
}
}
//查询缓存的购买交易
public void queryUncompleteOrder(String payType){
if (mGoogleBillingClient == null){
String msg = "queryPurchases billingClient is null";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
return;
}
mGoogleBillingClient.queryPurchasesAsync(payType, (billingResult, list) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "Billing client was null or result code is:" + billingResult.getDebugMessage());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
} else {
//消耗
JSONArray jsonArray = new JSONArray();
for (Purchase purchase : list){
//商品购买成功系统还会生成购买令牌它是一个唯一标识符表示用户及其所购应用内商品的商品 I
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()){
mPurchase.put(purchase.getPurchaseToken(), purchase);
//验证签名
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("payType", payType);
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
boolean succ = verifyValidSignature(originalJson,signature);
productInfo.put("signtureFlag", String.valueOf(succ));
productInfo.put("purchaseState", "1");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING){
ArrayList<String> skus = purchase.getSkus();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("purchaseState", "2");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, jsonArray.toString());
}
});
}
//查询缓存的訂閲状态
public void querySubscribeOrder(String payType) {
if (mGoogleBillingClient == null) {
String msg = "queryPurchases billingClient is null";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
return;
}
mGoogleBillingClient.queryPurchasesAsync(payType, (billingResult, list) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "Billing client was null or result code is:" + billingResult.getDebugMessage());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
} else {
//消耗
JSONArray jsonArray = new JSONArray();
for (Purchase purchase : list){
//商品购买成功系统还会生成购买令牌它是一个唯一标识符表示用户及其所购应用内商品的商品 I
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("payType", payType);
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
boolean succ = verifyValidSignature(originalJson,signature);
productInfo.put("signtureFlag", String.valueOf(succ));
productInfo.put("purchaseState", "1");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}
Log.d(LOG_TAG, "订阅状态查询 " + jsonArray.toString());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, jsonArray.toString());
}
});
}
private boolean verifyValidSignature(String signedData, String signature) {
return Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature);
}
public void onDestroy(){
if (mGoogleBillingClient != null && mGoogleBillingClient.isReady()){
mGoogleBillingClient.endConnection();
mGoogleBillingClient = null;
}
}
}

View File

@ -0,0 +1,96 @@
package com.juzu.dz.third;
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.NonNull;
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.ApiException;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import org.json.JSONException;
import org.json.JSONObject;
import com.juzu.dz.message.BFMessage;
public class GoogleLogin {
private static volatile GoogleLogin sInstance;
private GoogleSignInClient mGoogleSignInClient;
private static final int REQUEST_CODE_GOOGLE_SIGN_IN = 1001; /* unique request id */
private static final String server_client_token = "526230333982-j465cnveghnr5el3701rtsc38s3l08cg.apps.googleusercontent.com";
public static GoogleLogin getInstance()
{
if (sInstance == null) {
synchronized (GoogleLogin.class) {
if (sInstance == null) {
sInstance = new GoogleLogin();
}
}
}
return sInstance;
}
public void init(Activity activity){
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestId()
.requestIdToken(server_client_token)
.requestServerAuthCode(server_client_token)
.requestScopes(new Scope(Scopes.PLUS_ME))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(activity, gso);
}
public void login(Activity activity)
{
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
activity.startActivityForResult(signInIntent, REQUEST_CODE_GOOGLE_SIGN_IN);
}
public void logout(Activity activity)
{
mGoogleSignInClient.signOut().addOnCompleteListener(activity, new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGOUT_SUCCESS, "");
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_CODE_GOOGLE_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGIN_SUCCESS, createLoginInfo(account));
} catch (ApiException e) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGIN_FAILED, "google login failed e:" + e.getStatusCode() + " msg:" + e.getMessage());
}
}
private String createLoginInfo(GoogleSignInAccount account){
String idToken = account.getIdToken();
String uid = account.getId();
JSONObject result = new JSONObject();
try {
result.put("Token", idToken);
result.put("UserId", uid);
} catch (JSONException e) {
e.printStackTrace();
}
return result.toString();
}
}

View File

@ -0,0 +1,148 @@
package com.juzu.dz.third;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
// import com.google.firebase.messaging.FirebaseMessaging;
import com.juzu.dz.message.BFMessage;
import com.unity3d.player.UnityPlayer;
import org.json.JSONException;
import org.json.JSONObject;
public class GooglePlugin {
private static final String LOG_TAG = "GooglePlugin";
private static GoogleLogin mGoogleLogin = null;
private static GoogleBilling mGoogleBilling = null;
private static Activity _activity;
public static void init(Activity activity){
_activity = activity;
}
public static void initLogin()
{
if (mGoogleLogin == null)
{
mGoogleLogin = GoogleLogin.getInstance();
mGoogleLogin.init(_activity);
}
}
public static void initBilling()
{
if (mGoogleBilling == null)
{
mGoogleBilling = GoogleBilling.getInstance();
mGoogleBilling.init(_activity);
}
}
// 登录
public static void login()
{
if (mGoogleLogin != null){
mGoogleLogin.login(_activity);
}else{
sendMessageToUnity(BFMessage.GOOGLE_LOGIN_FAILED, "google login failed: not init");
}
}
// 登出
public static void logout()
{
if (mGoogleLogin != null){
mGoogleLogin.logout(_activity);
}else{
sendMessageToUnity(BFMessage.GOOGLE_LOGOUT_FAILED, "");
}
}
public static void pay(String payType, String productId, String customMsg)
{
if (mGoogleBilling != null){
mGoogleBilling.pay(_activity, payType, productId, customMsg);
}else{
sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, "billing not init");
}
}
public static void queryProductsInfo(String payType, String productJson)
{
if (mGoogleBilling != null){
mGoogleBilling.queryProductsInfo(payType, productJson);
}else{
sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, "billing not init");
}
}
public static void consumeAsync(String purchaseToken)
{
if (mGoogleBilling != null){
mGoogleBilling.consumeAsync(purchaseToken);
}else{
sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "billing not init");
}
}
public static void connectGoogleStore()
{
if (mGoogleBilling != null){
mGoogleBilling.connectGoogleStore();
}else{
sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, "billing not init");
}
}
public static void queryUncompleteOrder(String payType)
{
if (mGoogleBilling != null){
mGoogleBilling.queryUncompleteOrder(payType);
}else{
sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
}
}
public static void querySubscribeOrder(String payType)
{
if (mGoogleBilling != null){
mGoogleBilling.querySubscribeOrder(payType);
}else{
sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
}
}
public static void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (mGoogleLogin != null){
mGoogleLogin.onActivityResult(requestCode, resultCode, data);
}
}
public static void onDestroy()
{
if (mGoogleBilling != null){
mGoogleBilling.onDestroy();
}
}
public static void getFirebaseToken()
{
}
public static void sendMessageToUnity(int code, String msg){
JSONObject data = new JSONObject();
try {
data.put("head", code);
data.put("body", msg);
} catch (JSONException e) {
e.printStackTrace();
}
Log.d(LOG_TAG, code + ":" + msg);
UnityPlayer.UnitySendMessage("SDKManager", "MsgFromAndroidOrIOS", data.toString());
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2021 Google Inc. All rights reserved.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.juzu.dz.third;
/*
* This class is an sample of how you can check to make sure your purchases on the device came
* from Google Play. Putting code like this on your server will provide additional protection.
* <p>
* One thing that you may also wish to consider doing is caching purchase IDs to make replay
* attacks harder. The reason this code isn't just part of the library is to allow
* you to customize it (and rename it!) to make generic patching exploits more difficult.
*/
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
/**
* Security-related methods. For a secure implementation, all of this code should be implemented on
* a server that communicates with the application on the device.
*/
class Security {
static final private String TAG = "IABUtil/Security";
static final private String KEY_FACTORY_ALGORITHM = "RSA";
static final private String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* BASE_64_ENCODED_PUBLIC_KEY should be YOUR APPLICATION PUBLIC KEY. You currently get this
* from the Google Play developer console under the "Monetization Setup" category in the
* Licensing area. This build has been setup so that if you define base64EncodedPublicKey in
* your local.properties, it will be echoed into BuildConfig.
*/
/**
* Verifies that the data was signed with the given signature
*
* @param signedData the signed JSON string (signed, not encrypted)
* @param signature the signature for the data, signed with the private key
*/
static public boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if ((TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
|| TextUtils.isEmpty(signature))
) {
Log.w(TAG, "Purchase verification failed: missing data.");
return false;
}
try {
PublicKey key = generatePublicKey(base64PublicKey);
return verify(key, signedData, signature);
} catch (IOException e) {
Log.e(TAG, "Error generating PublicKey from encoded key: " + e.getMessage());
return false;
}
}
/**
* Generates a PublicKey instance from a string containing the Base64-encoded public key.
*
* @param encodedPublicKey Base64-encoded public key
* @throws IOException if encoding algorithm is not supported or key specification
* is invalid
*/
static private PublicKey generatePublicKey(String encodedPublicKey) throws IOException {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
String msg = "Invalid key specification: " + e;
Log.w(TAG, msg);
throw new IOException(msg);
}
}
/**
* Verifies that the signature from the server matches the computed signature on the data.
* Returns true if the data is correctly signed.
*
* @param publicKey public key associated with the developer account
* @param signedData signed data from server
* @param signature server signature
* @return true if the data and signature match
*/
static private Boolean verify(PublicKey publicKey, String signedData, String signature) {
byte[] signatureBytes;
try {
signatureBytes = Base64.decode(signature, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Base64 decoding failed.");
return false;
}
try {
Signature signatureAlgorithm = Signature.getInstance(SIGNATURE_ALGORITHM);
signatureAlgorithm.initVerify(publicKey);
signatureAlgorithm.update(signedData.getBytes());
if (!signatureAlgorithm.verify(signatureBytes)) {
Log.w(TAG, "Signature verification failed...");
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key specification.");
} catch (SignatureException e) {
Log.e(TAG, "Signature exception.");
}
return false;
}
}

View File

@ -1,174 +1,174 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import android.os.Build;
import com.juzu.dz.third.GooglePlugin;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import android.os.Build;
import com.juzu.dz.third.GooglePlugin;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>

82
BFVersions/android/dz_google_apk/build.gradle Normal file → Executable file
View File

@ -1,40 +1,42 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.google.gms:google-services:4.3.13'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
mavenCentral()
maven { url 'https://artifacts.applovin.com/android'; content { includeGroupByRegex 'com.applovin.*' } }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.google.gms:google-services:4.3.13'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
classpath 'com.applovin.quality:AppLovinQualityServiceGradlePlugin:+'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

11
BFVersions/android/dz_google_apk/gradle.properties Normal file → Executable file
View File

@ -1,5 +1,6 @@
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true
unityStreamingAssets=.unity3d, .bytes, .ab, UnityServicesProjectConfiguration.json
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true
unityStreamingAssets=.unity3d, .bytes, .ab, UnityServicesProjectConfiguration.json
unityTemplateVersion=4

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ironsource.unity">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
<!-- AdMob -->
<!--As Requiered By Admob please add your App ID-->
<!--<meta-data-->
<!--android:name="com.google.android.gms.ads.APPLICATION_ID"-->
<!--android:value="YOUR_ADMOB_APP_ID"/>-->
</application>
</manifest>

View File

@ -1,28 +0,0 @@
apply plugin: 'android-library'
dependencies {
implementation fileTree(dir: 'bin', include: ['*.jar'])
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
//java.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
compileSdkVersion 34
buildToolsVersion '30.0.2'
defaultConfig {
targetSdkVersion 34
}
lintOptions {
abortOnError false
}
}

View File

@ -1,2 +0,0 @@
target=android-9
android.library=true

View File

@ -1,206 +1,203 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
// Android Resolver Repos Start
([rootProject] + (rootProject.subprojects as List)).each { project ->
project.repositories {
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
maven {
url "https://maven.google.com"
}
maven {
url "https://android-sdk.is.com/" // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:9, Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:16, Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:16, Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:8, Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:8, Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:16, Assets/IronSource/Editor/ISFyberAdapterDependencies.xml:16, Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:48, Assets/IronSource/Editor/ISPangleAdapterDependencies.xml:8, Assets/IronSource/Editor/ISTapJoyAdapterDependencies.xml:8, Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:8, Assets/IronSource/Editor/ISVungleAdapterDependencies.xml:16, Assets/IronSourceAdQuality/Editor/IronSourceAdQualityDependencies.xml:9, Assets/IronSourceAdQuality/Editor/IronSourceAdQualityDependencies.xml:17
}
maven {
url "https://maven.google.com/" // Assets/IronSource/Editor/IronSourceSDKDependencies.xml:17, Assets/IronSource/Editor/IronSourceSDKDependencies.xml:25, Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:8, Assets/IronSource/Editor/ISAdMobAdapterDependencies.xml:8, Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:15, Assets/IronSource/Editor/ISFacebookAdapterDependencies.xml:8, Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:40, Assets/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:15
}
maven {
url "https://cboost.jfrog.io/artifactory/chartboost-ads/" // Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:15
}
maven {
url "https://repo.maven.apache.org/maven2/" // Assets/IronSource/Editor/ISFyberAdapterDependencies.xml:8
}
maven {
url "https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea/" // Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:8, Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:16, Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:24, Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:32
}
maven {
url "https://artifact.bytedance.com/repository/pangle/" // Assets/IronSource/Editor/ISPangleAdapterDependencies.xml:15
}
maven {
url "https://sdk.tapjoy.com/" // Assets/IronSource/Editor/ISTapJoyAdapterDependencies.xml:15
}
maven {
url "https://jitpack.io/" // Assets/IronSource/Editor/ISVungleAdapterDependencies.xml:8
}
mavenLocal()
jcenter()
mavenCentral()
}
}
// Android Resolver Repos End
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:multidex:1.0.3'
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation(name: 'facebook-android-wrapper-15.1.0', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:6.2.1"
// firebase
implementation 'com.google.firebase:firebase-analytics:21.1.0'
implementation 'com.google.firebase:firebase-crashlytics:18.2.12'
implementation 'com.google.firebase:firebase-messaging:23.0.8'
// adjust
implementation(name: 'adjust-android-signaturev2-v2.15.10-s2', ext:'aar')
implementation project('IronSource.androidlib')
// Android Resolver Dependencies Start
implementation 'androidx.recyclerview:recyclerview:1.2.1' // Assets/IronSource/Editor/ISMintegralAdapterDependencies.xml:40
implementation 'com.adcolony:sdk:4.8.0' // Assets/IronSource/Editor/ISAdColonyAdapterDependencies.xml:8
implementation 'com.android.installreferrer:installreferrer:2.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:10
implementation 'com.android.support:appcompat-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:cardview-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:customtabs:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:support-v4:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.applovin:applovin-sdk:11.10.1' // Assets/IronSource/Editor/ISAppLovinAdapterDependencies.xml:15
implementation 'com.appsflyer:af-android-sdk:6.4.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:6
implementation 'com.appsflyer:unity-wrapper:6.4.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:8
implementation 'com.appsflyer:adrevenue:6.5.4' // Assets/ThirdParty/AppsFlyerAdrevenue/Editor/AppsFlyerAdRevenueDependencies.xml:4
implementation 'com.appsflyer:unity-adrevenue-generic-wrapper:6.5.4' // Assets/ThirdParty/AppsFlyerAdrevenue/Editor/AppsFlyerAdRevenueDependencies.xml:5
implementation 'com.chartboost:chartboost-sdk:9.3.1' // Assets/IronSource/Editor/ISChartboostAdapterDependencies.xml:15
implementation 'com.facebook.android:audience-network-sdk:6.16.0' // Assets/ThirdParty/IronSource/Editor/ISFacebookAdapterDependencies.xml:8
implementation 'com.facebook.android:facebook-applinks:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:6
implementation 'com.facebook.android:facebook-core:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:5
implementation 'com.facebook.android:facebook-gamingservices:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:9
implementation 'com.facebook.android:facebook-login:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:7
implementation 'com.facebook.android:facebook-share:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:8
implementation 'com.fyber:marketplace-sdk:8.2.4' // Assets/ThirdParty/IronSource/Editor/ISFyberAdapterDependencies.xml:8
implementation 'com.google.android.gms:play-services-ads:22.2.0' // Assets/ThirdParty/IronSource/Editor/ISAdMobAdapterDependencies.xml:8
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' // Assets/ThirdParty/IronSource/Editor/IronSourceSDKDependencies.xml:17
implementation 'com.google.android.gms:play-services-basement:18.1.0' // Assets/ThirdParty/IronSource/Editor/IronSourceSDKDependencies.xml:25
implementation 'com.ironsource.adapters:adcolonyadapter:4.3.15' // Assets/ThirdParty/IronSource/Editor/ISAdColonyAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:admobadapter:4.3.39' // Assets/ThirdParty/IronSource/Editor/ISAdMobAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:applovinadapter:4.3.39' // Assets/ThirdParty/IronSource/Editor/ISAppLovinAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:chartboostadapter:4.3.12' // Assets/ThirdParty/IronSource/Editor/ISChartboostAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:facebookadapter:4.3.45' // Assets/ThirdParty/IronSource/Editor/ISFacebookAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:fyberadapter:4.3.28' // Assets/ThirdParty/IronSource/Editor/ISFyberAdapterDependencies.xml:16
implementation 'com.ironsource.adapters:mintegraladapter:4.3.19' // Assets/ThirdParty/IronSource/Editor/ISMintegralAdapterDependencies.xml:48
implementation 'com.ironsource.adapters:pangleadapter:4.3.22' // Assets/ThirdParty/IronSource/Editor/ISPangleAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:tapjoyadapter:4.1.25' // Assets/ThirdParty/IronSource/Editor/ISTapJoyAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:unityadsadapter:4.3.33' // Assets/ThirdParty/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:8
implementation 'com.ironsource.adapters:vungleadapter:4.3.22' // Assets/ThirdParty/IronSource/Editor/ISVungleAdapterDependencies.xml:16
implementation 'com.ironsource.sdk:mediationsdk:7.5.1' // Assets/ThirdParty/IronSource/Editor/IronSourceSDKDependencies.xml:9
implementation 'com.mbridge.msdk.oversea:mbbanner:16.5.21' // Assets/ThirdParty/IronSource/Editor/ISMintegralAdapterDependencies.xml:24
implementation 'com.mbridge.msdk.oversea:mbbid:16.5.21' // Assets/ThirdParty/IronSource/Editor/ISMintegralAdapterDependencies.xml:32
implementation 'com.mbridge.msdk.oversea:newinterstitial:16.5.21' // Assets/ThirdParty/IronSource/Editor/ISMintegralAdapterDependencies.xml:8
implementation 'com.mbridge.msdk.oversea:reward:16.5.21' // Assets/ThirdParty/IronSource/Editor/ISMintegralAdapterDependencies.xml:16
implementation 'com.pangle.global:ads-sdk:5.5.0.5' // Assets/ThirdParty/IronSource/Editor/ISPangleAdapterDependencies.xml:15
implementation 'com.parse.bolts:bolts-android:1.4.0' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:4
implementation 'com.tapjoy:tapjoy-android-sdk:13.0.1' // Assets/ThirdParty/IronSource/Editor/ISTapJoyAdapterDependencies.xml:15
implementation 'com.unity3d.ads:unity-ads:4.9.1' // Assets/ThirdParty/IronSource/Editor/ISUnityAdsAdapterDependencies.xml:15
implementation 'com.vungle:vungle-ads:7.0.0' // Assets/ThirdParty/IronSource/Editor/ISVungleAdapterDependencies.xml:8
// Android Resolver Dependencies End
constraints {
implementation('androidx.work:work-runtime:2.7.0') {
because '''androidx.work:work-runtime:2.1.0 pulled from
play-services-ads has a bug using PendingIntent without
FLAG_IMMUTABLE or FLAG_MUTABLE and will fail in Apps
targeting S+.'''
}
}
}
android {
compileSdkVersion 34
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
defaultConfig {
minSdkVersion 24
targetSdkVersion 34
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
}
}
def getSdkDir() {
Properties local = new Properties()
local.load(new FileInputStream("${rootDir}/local.properties"))
return local.getProperty('sdk.dir')
}
def BuildIl2Cpp(String workingDir, String targetDirectory, String architecture, String abi, String configuration) {
exec {
commandLine(workingDir + "/src/main/Il2CppOutputProject/IL2CPP/build/deploy/netcoreapp3.1/il2cpp",
"--compile-cpp",
"--libil2cpp-static",
"--platform=Android",
"--architecture=" + architecture,
"--configuration=" + configuration,
"--outputpath=" + workingDir + targetDirectory + abi + "/libil2cpp.so",
"--cachedirectory=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_cache",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/external/bdwgc/include",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/libil2cpp/include",
"--tool-chain-path=" + android.ndkDirectory,
"--map-file-parser=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/MapFileParser/MapFileParser.exe",
"--generatedcppdir=" + workingDir + "/src/main/Il2CppOutputProject/Source/il2cppOutput",
"--baselib-directory=" + workingDir + "/src/main/jniStaticLibs/" + abi,
"--dotnetprofile=unityaot")
environment "ANDROID_SDK_ROOT", getSdkDir()
}
delete workingDir + targetDirectory + abi + "/libil2cpp.sym.so"
ant.move(file: workingDir + targetDirectory + abi + "/libil2cpp.dbg.so", tofile: workingDir + "/symbols/" + abi + "/libil2cpp.so")
}
android {
task BuildIl2CppTask {
doLast {
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARMv7', 'armeabi-v7a', 'Release');
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARM64', 'arm64-v8a', 'Release');
}
}
afterEvaluate {
if (project(':unityLibrary').tasks.findByName('mergeDebugJniLibFolders'))
project(':unityLibrary').mergeDebugJniLibFolders.dependsOn BuildIl2CppTask
if (project(':unityLibrary').tasks.findByName('mergeReleaseJniLibFolders'))
project(':unityLibrary').mergeReleaseJniLibFolders.dependsOn BuildIl2CppTask
}
sourceSets {
main {
jni.srcDirs = ["src/main/Il2CppOutputProject"]
}
}
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
// Android Resolver Repos Start
([rootProject] + (rootProject.subprojects as List)).each { project ->
project.repositories {
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
maven {
url "https://maven.google.com"
}
maven {
url "https://verve.jfrog.io/artifactory/verve-gradle-release" // Assets/ThirdParty/MaxSdk/Mediation/Verve/Editor/Dependencies.xml:7
}
maven {
url "https://artifactory.bidmachine.io/bidmachine" // Assets/ThirdParty/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml:8
}
maven {
url "https://cboost.jfrog.io/artifactory/chartboost-ads/" // Assets/ThirdParty/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml:8
}
maven {
url "https://android-sdk.is.com/" // Assets/ThirdParty/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml:8
}
maven {
url "https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea" // Assets/ThirdParty/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml:8
}
maven {
url "https://artifact.bytedance.com/repository/pangle" // Assets/ThirdParty/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml:8
}
maven { url "../Upload-TaurusX" }
maven {
url "https://bitbucket.org/sdkcenter/sdkcenter/raw/release"
}
mavenLocal()
jcenter()
mavenCentral()
}
}
// Android Resolver Repos End
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:multidex:1.0.3'
// IAB TCF Decoder
implementation("com.iabtcf:iabtcf-decoder:2.0.10")
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation(name: 'LofeltHaptics', ext:'aar')
implementation(name: 'facebook-android-wrapper-15.1.0', ext:'aar')
implementation(name: 'applovin-max-unity-plugin', ext:'aar')
implementation "com.android.billingclient:billing:6.2.1"
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation 'com.google.android.play:review:2.0.1'
// Android Resolver Dependencies Start
implementation 'com.google.firebase:firebase-analytics:21.4.0'
implementation 'com.google.firebase:firebase-crashlytics:18.5.0'
implementation 'com.google.firebase:firebase-messaging:23.3.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1' // Assets/ThirdParty/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml:9
implementation 'com.android.installreferrer:installreferrer:2.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:10
implementation 'com.android.support:appcompat-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:cardview-v7:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.android.support:customtabs:28.+' // Assets/ThirdParty/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml:7
implementation 'com.android.support:recyclerview-v7:28.+' // Assets/ThirdParty/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml:6
implementation 'com.android.support:support-v4:25.3.1' // Facebook.Unity.Editor.AndroidSupportLibraryResolver.addSupportLibraryDependency
implementation 'com.applovin.mediation:bidmachine-adapter:3.2.1.0' // Assets/ThirdParty/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml:8
implementation 'com.applovin.mediation:bigoads-adapter:5.2.1.0' // Assets/ThirdParty/MaxSdk/Mediation/BigoAds/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:bytedance-adapter:6.5.0.8.1' // Assets/ThirdParty/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml:8
implementation 'com.applovin.mediation:chartboost-adapter:9.8.3.0' // Assets/ThirdParty/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml:8
implementation 'com.applovin.mediation:facebook-adapter:[6.19.0.2]' // Assets/ThirdParty/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml:8
implementation 'com.applovin.mediation:fyber-adapter:8.3.6.1' // Assets/ThirdParty/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:google-adapter:[24.2.0.0]' // Assets/ThirdParty/MaxSdk/Mediation/Google/Editor/Dependencies.xml:5
implementation 'com.applovin.mediation:google-ad-manager-adapter:[24.2.0.0]' // Assets/ThirdParty/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml:5
implementation 'com.applovin.mediation:inmobi-adapter:10.8.2.0' // Assets/ThirdParty/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:ironsource-adapter:8.7.0.0.0' // Assets/ThirdParty/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml:8
implementation 'com.applovin.mediation:line-adapter:2025.1.10.1' // Assets/ThirdParty/MaxSdk/Mediation/Line/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:mobilefuse-adapter:1.9.0.0' // Assets/ThirdParty/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:moloco-adapter:3.8.0.0' // Assets/ThirdParty/MaxSdk/Mediation/Moloco/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:mytarget-adapter:5.27.1.2' // Assets/ThirdParty/MaxSdk/Mediation/MyTarget/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:unityads-adapter:4.14.1.0' // Assets/ThirdParty/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:verve-adapter:3.3.0.0' // Assets/ThirdParty/MaxSdk/Mediation/Verve/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:vungle-adapter:7.4.3.2' // Assets/ThirdParty/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml:4
implementation 'com.applovin.mediation:mintegral-adapter:16.9.61.0' // Assets/ThirdParty/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml:8
implementation 'com.applovin.mediation:yandex-adapter:7.9.0.1' // Assets/ThirdParty/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml:4
implementation "com.taurusx.tax:ads:1.5.4" // Assets/ThirdParty/MaxSdk/Mediation/TaurusX/Editor/Dependencies.xml:4
implementation "com.applovin.mediation:taurusXAdapters:1.3.0.1"
implementation 'com.applovin:applovin-sdk:13.1.0' // Assets/ThirdParty/MaxSdk/AppLovin/Editor/Dependencies.xml:4
implementation 'com.appsflyer:adrevenue:6.9.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml:4
implementation 'com.appsflyer:unity-adrevenue-generic-wrapper:6.9.1' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml:5
implementation 'com.appsflyer:af-android-sdk:6.13.0' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:6
implementation 'com.appsflyer:unity-wrapper:6.13.10' // Assets/ThirdParty/AppsFlyer/Editor/AppsFlyerDependencies.xml:8
implementation 'com.facebook.android:facebook-applinks:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:6
implementation 'com.facebook.android:facebook-core:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:5
implementation 'com.facebook.android:facebook-gamingservices:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:9
implementation 'com.facebook.android:facebook-login:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:7
implementation 'com.facebook.android:facebook-share:[15.1,16)' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:8
implementation 'com.google.android.gms:play-services-base:16.1.0' // Assets/ThirdParty/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml:9
implementation 'com.parse.bolts:bolts-android:1.4.0' // Assets/ThirdParty/FacebookSDK/Plugins/Editor/Dependencies.xml:4
implementation 'com.squareup.picasso:picasso:2.71828' // Assets/ThirdParty/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml:5
implementation 'com.google.android.ump:user-messaging-platform:2.1.0'
// Android Resolver Dependencies End
}
android {
compileSdkVersion 34
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
defaultConfig {
minSdkVersion 24
targetSdkVersion 34
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
}
}
def getSdkDir() {
Properties local = new Properties()
local.load(new FileInputStream("${rootDir}/local.properties"))
return local.getProperty('sdk.dir')
}
def BuildIl2Cpp(String workingDir, String configuration, String architecture, String abi, String[] staticLibraries) {
def commandLineArgs = []
commandLineArgs.add("--compile-cpp")
commandLineArgs.add("--platform=Android")
commandLineArgs.add("--architecture=" + architecture)
commandLineArgs.add("--outputpath=" + workingDir + "/src/main/jniLibs/" + abi + "/libil2cpp.so")
commandLineArgs.add("--libil2cpp-static")
commandLineArgs.add("--baselib-directory=" + workingDir + "/src/main/jniStaticLibs/" + abi)
commandLineArgs.add("--incremental-g-c-time-slice=3")
commandLineArgs.add("--configuration=" + configuration)
commandLineArgs.add("--dotnetprofile=unityaot-linux")
commandLineArgs.add("--profiler-report")
commandLineArgs.add("--profiler-output-file=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_conv.traceevents")
commandLineArgs.add("--print-command-line")
commandLineArgs.add("--generatedcppdir=" + workingDir + "/src/main/Il2CppOutputProject/Source/il2cppOutput")
commandLineArgs.add("--cachedirectory=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_cache")
commandLineArgs.add("--tool-chain-path=" + android.ndkDirectory)
staticLibraries.eachWithIndex {fileName, i->
commandLineArgs.add("--additional-libraries=" + workingDir + "/src/main/jniStaticLibs/" + abi + "/" + fileName)
}
def executableExtension = ""
if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
executableExtension = ".exe"
commandLineArgs = commandLineArgs*.replace('\"', '\\\"')
}
exec {
executable workingDir + "/src/main/Il2CppOutputProject/IL2CPP/build/deploy/il2cpp" + executableExtension
args commandLineArgs
environment "ANDROID_SDK_ROOT", getSdkDir()
}
delete workingDir + "/src/main/jniLibs/" + abi + "/libil2cpp.sym.so"
ant.move(file: workingDir + "/src/main/jniLibs/" + abi + "/libil2cpp.dbg.so", tofile: workingDir + "/symbols/" + abi + "/libil2cpp.so")
}
android {
task BuildIl2CppTask {
doLast {
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), 'Release', 'armv7', 'armeabi-v7a', [ ] as String[]);
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), 'Release', 'arm64', 'arm64-v8a', [ ] as String[]);
}
}
afterEvaluate {
if (project(':unityLibrary').tasks.findByName('mergeDebugJniLibFolders'))
project(':unityLibrary').mergeDebugJniLibFolders.dependsOn BuildIl2CppTask
if (project(':unityLibrary').tasks.findByName('mergeReleaseJniLibFolders'))
project(':unityLibrary').mergeReleaseJniLibFolders.dependsOn BuildIl2CppTask
}
sourceSets {
main {
jni.srcDirs = ["src/main/Il2CppOutputProject"]
}
}
}

View File

@ -1,79 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<!-- [START firebase_service] -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/firebase_icon" />
<service
android:name="com.juzu.dz.third.BFFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
<activity android:name="com.facebook.unity.FBUnityLoginActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityDialogsActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityGamingServicesFriendFinderActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityAppLinkActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityDeepLinkingActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityGameRequestActivity" />
<activity android:name="com.facebook.unity.FBUnityCreateGameGroupActivity" />
<activity android:name="com.facebook.unity.FBUnityJoinGameGroupActivity" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb277827051329111" />
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="cd6be8cc57dff789f3476ee1b25e2410"/>
<meta-data android:name="com.facebook.sdk.AutoLogAppEventsEnabled" android:value="true" />
<meta-data android:name="com.facebook.sdk.AdvertiserIDCollectionEnabled" android:value="true" />
<provider android:name="com.facebook.FacebookContentProvider" android:authorities="com.facebook.app.FacebookContentProvider277827051329111" android:exported="true" />
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8252390069143459~7841203986"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
android:value="true"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
android:value="true"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<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.WAKE_LOCK”"/>
<uses-permission android:name='android.permission.POST_NOTIFICATIONS'/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<!-- [START firebase_service] -->
<!-- <meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/firebase_icon" />
<service
android:name="com.juzu.dz.third.BFFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service> -->
<!-- [END firebase_service] -->
<activity android:name="com.facebook.unity.FBUnityLoginActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityDialogsActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityGamingServicesFriendFinderActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity android:name="com.facebook.unity.FBUnityAppLinkActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityDeepLinkingActivity" android:exported="true" />
<activity android:name="com.facebook.unity.FBUnityGameRequestActivity" />
<activity android:name="com.facebook.unity.FBUnityCreateGameGroupActivity" />
<activity android:name="com.facebook.unity.FBUnityJoinGameGroupActivity" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb491773936518549" />
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="2d2cb45aeb5ddb18189e8b7378ddcaa5"/>
<meta-data android:name="com.facebook.sdk.AutoLogAppEventsEnabled" android:value="true" />
<meta-data android:name="com.facebook.sdk.AdvertiserIDCollectionEnabled" android:value="true" />
<provider android:name="com.facebook.FacebookContentProvider" android:authorities="com.facebook.app.FacebookContentProvider491773936518549" android:exported="true" />
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!--本地推送-->
<receiver android:name="com.unity.androidnotifications.UnityNotificationManager" android:exported="false" />
<receiver android:name="com.unity.androidnotifications.UnityNotificationRestartOnBootReceiver" android:enabled="false" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<meta-data android:name="com.unity.androidnotifications.exact_scheduling" android:value="0" />
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8252390069143459~5042842686"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
android:value="true"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
android:value="true"/>
<meta-data android:name="applovin.sdk.key" android:value="9uHgeBwag3NXva9MC23ToO3q11Ve59bF1uwg4qGltdGmCQ7OSByFZ_3b1ZF7krMlkHQo5gXzIokVDsvg1rwbr-" />
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
<!-- REPLACE_BUILD_ID -->
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<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.WAKE_LOCK"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="android.permission.VIBRATE" />
</manifest>

View File

@ -1,188 +1,179 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import android.os.Build;
// import com.chartboost.sdk.Chartboost;
import com.juzu.dz.third.GooglePlugin;
import com.ironsource.mediationsdk.IronSource;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
IronSource.onPause(this);
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
IronSource.onResume(this);
}
@Override
public void onBackPressed() {
// If an interstitial is on screen, close it.
// if (Chartboost.onBackPressed()) {
// return;
// } else {
// super.onBackPressed();
// }
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import com.chartboost.sdk.Chartboost;
import com.juzu.dz.third.GooglePlugin;
// import com.ironsource.mediationsdk.IronSource;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
MultiWindowSupport.saveMultiWindowMode(this);
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
// IronSource.onPause(this);
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this) && !MultiWindowSupport.isMultiWindowModeChangedToTrue(this))
return;
mUnityPlayer.resume();
// IronSource.onResume(this);
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>

80
BFVersions/android/dz_release/build.gradle Normal file → Executable file
View File

@ -1,40 +1,40 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.google.gms:google-services:4.3.13'
// classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.google.gms:google-services:4.3.13'
// classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
}
}
allprojects {
buildscript {
repositories {
google()
jcenter()
}
// dependencies {
// classpath 'com.android.tools.build:gradle:4.0.1'
//
// }
}
repositories {
google()
jcenter()
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

10
BFVersions/android/dz_release/gradle.properties Normal file → Executable file
View File

@ -1,6 +1,6 @@
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
org.gradle.jvmargs=-Xmx4096M
org.gradle.parallel=true
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
unityStreamingAssets=.unity3d, .bytes, .ab

256
BFVersions/android/dz_release/unityLibrary/build.gradle Normal file → Executable file
View File

@ -1,128 +1,128 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:multidex:1.0.3'
implementation(name: 'androidx.activity.activity-1.0.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-1.1.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-resources-1.1.0', ext:'aar')
// implementation(name: 'androidx.browser.browser-1.0.0', ext:'aar')
implementation(name: 'androidx.cardview.cardview-1.0.0', ext:'aar')
implementation(name: 'androidx.core.core-ktx-1.3.2', ext:'aar')
implementation(name: 'androidx.legacy.legacy-support-v4-1.0.0', ext:'aar')
implementation(name: 'androidx.savedstate.savedstate-1.0.0', ext:'aar')
implementation(name: 'androidx.vectordrawable.vectordrawable-animated-1.1.0', ext:'aar')
implementation(name: 'com.android.installreferrer.installreferrer-2.1', ext:'aar')
implementation(name: 'com.appsflyer.af-android-sdk-6.4.1', ext:'aar')
implementation(name: 'com.appsflyer.oaid-6.2.4', ext:'aar')
implementation(name: 'com.appsflyer.unity-wrapper-6.4.1', ext:'aar')
implementation(name: 'com.facebook.android.facebook-applinks-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-common-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-core-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-gamingservices-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-login-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-share-11.3.0', ext:'aar')
implementation(name: 'facebook-android-wrapper-11.0.0', ext:'aar')
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:5.0.0"
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation 'com.google.firebase:firebase-analytics:21.1.0'
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.android.gms:play-services-ads:21.0.0'
implementation 'com.google.ads.mediation:facebook:6.11.0.1'
implementation 'com.unity3d.ads:unity-ads:4.2.1'
implementation 'com.google.ads.mediation:unity:4.2.1.1'
implementation 'com.google.ads.mediation:applovin:11.4.4.0'
implementation(name: 'mediationsdk-7.2.3.1', ext:'aar')
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
ndk {
abiFilters 'armeabi-v7a'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
}
}
def getSdkDir() {
Properties local = new Properties()
local.load(new FileInputStream("${rootDir}/local.properties"))
return local.getProperty('sdk.dir')
}
def BuildIl2Cpp(String workingDir, String targetDirectory, String architecture, String abi, String configuration) {
exec {
commandLine(workingDir + "/src/main/Il2CppOutputProject/IL2CPP/build/deploy/netcoreapp3.1/il2cpp",
"--compile-cpp",
"--libil2cpp-static",
"--platform=Android",
"--architecture=" + architecture,
"--configuration=" + configuration,
"--outputpath=" + workingDir + targetDirectory + abi + "/libil2cpp.so",
"--cachedirectory=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_cache",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/external/bdwgc/include",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/libil2cpp/include",
"--tool-chain-path=" + android.ndkDirectory,
"--map-file-parser=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/MapFileParser/MapFileParser.exe",
"--generatedcppdir=" + workingDir + "/src/main/Il2CppOutputProject/Source/il2cppOutput",
"--baselib-directory=" + workingDir + "/src/main/jniStaticLibs/" + abi,
"--dotnetprofile=unityaot")
environment "ANDROID_SDK_ROOT", getSdkDir()
}
delete workingDir + targetDirectory + abi + "/libil2cpp.sym.so"
ant.move(file: workingDir + targetDirectory + abi + "/libil2cpp.dbg.so", tofile: workingDir + "/symbols/" + abi + "/libil2cpp.so")
}
android {
task BuildIl2CppTask {
doLast {
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARMv7', 'armeabi-v7a', 'Release');
}
}
afterEvaluate {
if (project(':unityLibrary').tasks.findByName('mergeDebugJniLibFolders'))
project(':unityLibrary').mergeDebugJniLibFolders.dependsOn BuildIl2CppTask
if (project(':unityLibrary').tasks.findByName('mergeReleaseJniLibFolders'))
project(':unityLibrary').mergeReleaseJniLibFolders.dependsOn BuildIl2CppTask
}
sourceSets {
main {
jni.srcDirs = ["src/main/Il2CppOutputProject"]
}
}
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:multidex:1.0.3'
implementation(name: 'androidx.activity.activity-1.0.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-1.1.0', ext:'aar')
implementation(name: 'androidx.appcompat.appcompat-resources-1.1.0', ext:'aar')
// implementation(name: 'androidx.browser.browser-1.0.0', ext:'aar')
implementation(name: 'androidx.cardview.cardview-1.0.0', ext:'aar')
implementation(name: 'androidx.core.core-ktx-1.3.2', ext:'aar')
implementation(name: 'androidx.legacy.legacy-support-v4-1.0.0', ext:'aar')
implementation(name: 'androidx.savedstate.savedstate-1.0.0', ext:'aar')
implementation(name: 'androidx.vectordrawable.vectordrawable-animated-1.1.0', ext:'aar')
implementation(name: 'com.android.installreferrer.installreferrer-2.1', ext:'aar')
implementation(name: 'com.appsflyer.af-android-sdk-6.4.1', ext:'aar')
implementation(name: 'com.appsflyer.oaid-6.2.4', ext:'aar')
implementation(name: 'com.appsflyer.unity-wrapper-6.4.1', ext:'aar')
implementation(name: 'com.facebook.android.facebook-applinks-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-common-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-core-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-gamingservices-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-login-11.3.0', ext:'aar')
implementation(name: 'com.facebook.android.facebook-share-11.3.0', ext:'aar')
implementation(name: 'facebook-android-wrapper-11.0.0', ext:'aar')
implementation(name: 'screenutils-release', ext:'aar')
implementation(name: 'ThinkingSDK', ext:'aar')
implementation(name: 'UnityUtils-release', ext:'aar')
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation "com.android.billingclient:billing:4.0.0"
implementation platform('com.google.firebase:firebase-bom:29.2.1')
implementation 'com.google.firebase:firebase-analytics:21.1.0'
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.android.gms:play-services-ads:21.0.0'
implementation 'com.google.ads.mediation:facebook:6.11.0.1'
implementation 'com.unity3d.ads:unity-ads:4.2.1'
implementation 'com.google.ads.mediation:unity:4.2.1.1'
implementation 'com.google.ads.mediation:applovin:11.4.4.0'
implementation(name: 'mediationsdk-7.2.3.1', ext:'aar')
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
ndk {
abiFilters 'armeabi-v7a'
}
versionCode 1
versionName '0.1.0'
consumerProguardFiles 'proguard-unity.txt'
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
}
}
def getSdkDir() {
Properties local = new Properties()
local.load(new FileInputStream("${rootDir}/local.properties"))
return local.getProperty('sdk.dir')
}
def BuildIl2Cpp(String workingDir, String targetDirectory, String architecture, String abi, String configuration) {
exec {
commandLine(workingDir + "/src/main/Il2CppOutputProject/IL2CPP/build/deploy/netcoreapp3.1/il2cpp",
"--compile-cpp",
"--libil2cpp-static",
"--platform=Android",
"--architecture=" + architecture,
"--configuration=" + configuration,
"--outputpath=" + workingDir + targetDirectory + abi + "/libil2cpp.so",
"--cachedirectory=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_cache",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/external/bdwgc/include",
"--additional-include-directories=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/libil2cpp/include",
"--tool-chain-path=" + android.ndkDirectory,
"--map-file-parser=" + workingDir + "/src/main/Il2CppOutputProject/IL2CPP/MapFileParser/MapFileParser.exe",
"--generatedcppdir=" + workingDir + "/src/main/Il2CppOutputProject/Source/il2cppOutput",
"--baselib-directory=" + workingDir + "/src/main/jniStaticLibs/" + abi,
"--dotnetprofile=unityaot")
environment "ANDROID_SDK_ROOT", getSdkDir()
}
delete workingDir + targetDirectory + abi + "/libil2cpp.sym.so"
ant.move(file: workingDir + targetDirectory + abi + "/libil2cpp.dbg.so", tofile: workingDir + "/symbols/" + abi + "/libil2cpp.so")
}
android {
task BuildIl2CppTask {
doLast {
BuildIl2Cpp(projectDir.toString().replaceAll('\\\\', '/'), '/src/main/jniLibs/', 'ARMv7', 'armeabi-v7a', 'Release');
}
}
afterEvaluate {
if (project(':unityLibrary').tasks.findByName('mergeDebugJniLibFolders'))
project(':unityLibrary').mergeDebugJniLibFolders.dependsOn BuildIl2CppTask
if (project(':unityLibrary').tasks.findByName('mergeReleaseJniLibFolders'))
project(':unityLibrary').mergeReleaseJniLibFolders.dependsOn BuildIl2CppTask
}
sourceSets {
main {
jni.srcDirs = ["src/main/Il2CppOutputProject"]
}
}
}

View File

@ -1,54 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8252390069143459~7841203986"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
android:value="true"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
android:value="true"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<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.WAKE_LOCK”"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<meta-data android:name="unity.splash-mode" android:value="0" />
<meta-data android:name="unity.splash-enable" android:value="True" />
<meta-data android:name="unity.allow-resizable-window" android:value="False" />
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8252390069143459~1801140942"/>
<!-- <meta-data android:name="unity.build-id" android:value="49055670-6ef7-4715-954e-f4b0917c17e3" /> -->
<!-- 每次打包需要替换unity.build-id !-->
REPLACE_BUILD_ID
<!-- 刘海屏相关 -->
<!--华为-->
<meta-data android:name="android.notch_support" android:value="true" />
<!--小米-->
<meta-data android:name="notch.config" android:value="portrait|landscape" />
</application>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
</manifest>

View File

@ -1,188 +1,188 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import android.os.Build;
// import com.chartboost.sdk.Chartboost;
import com.juzu.dz.third.GooglePlugin;
import com.ironsource.mediationsdk.IronSource;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
IronSource.onPause(this);
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
IronSource.onResume(this);
}
@Override
public void onBackPressed() {
// If an interstitial is on screen, close it.
// if (Chartboost.onBackPressed()) {
// return;
// } else {
// super.onBackPressed();
// }
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
package com.unity3d.player;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;
// import android.os.Build;
import com.chartboost.sdk.Chartboost;
import com.juzu.dz.third.GooglePlugin;
import com.ironsource.mediationsdk.IronSource;
public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
// The command line arguments are passed as a string, separated by spaces
// UnityPlayerActivity calls this from 'onCreate'
// Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
// See https://docs.unity3d.com/Manual/CommandLineArguments.html
// @param cmdLine the current command line arguments, may be null
// @return the modified command line string or null
protected String updateUnityCommandLineArguments(String cmdLine)
{
return cmdLine;
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
getIntent().putExtra("unity", cmdLine);
mUnityPlayer = new UnityPlayer(this, this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
GooglePlugin.init(this);
}
// When Unity player unloaded move task to background
@Override public void onUnityPlayerUnloaded() {
moveTaskToBack(true);
}
// Callback before Unity player process is killed
@Override public void onUnityPlayerQuitted() {
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
mUnityPlayer.newIntent(intent);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GooglePlugin.onActivityResult(requestCode, resultCode, data);
}
// Quit Unity
@Override protected void onDestroy ()
{
GooglePlugin.onDestroy();
mUnityPlayer.destroy();
super.onDestroy();
}
// If the activity is in multi window mode or resizing the activity is allowed we will use
// onStart/onStop (the visibility callbacks) to determine when to pause/resume.
// Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
// existing behavior.
@Override protected void onStop()
{
super.onStop();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
}
@Override protected void onStart()
{
super.onStart();
if (!MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.pause();
IronSource.onPause(this);
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
if (MultiWindowSupport.getAllowResizableWindow(this))
return;
mUnityPlayer.resume();
IronSource.onResume(this);
}
@Override
public void onBackPressed() {
// If an interstitial is on screen, close it.
if (Chartboost.onBackPressed()) {
return;
} else {
super.onBackPressed();
}
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>

163
BFVersions/android/google_common/launcher/build.gradle Normal file → Executable file
View File

@ -1,72 +1,91 @@
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
dependencies {
implementation project(':unityLibrary')
}
android {
compileSdkVersion 34
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
defaultConfig {
minSdkVersion 24
targetSdkVersion 34
applicationId 'REPLACE_APPLICATION_ID'
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
versionCode 1
versionName '0.1.0'
multiDexEnabled true
}
aaptOptions {
noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
lintOptions {
abortOnError false
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
jniDebuggable true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
}
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
}
bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = true
}
}
}
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
apply plugin: 'com.android.application'
apply plugin: 'applovin-quality-service'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
applovin {
// NOTE: DO NOT CHANGE - this is NOT your AppLovin MAX SDK key - this is a derived key.
apiKey 'c88aa3b89fe7f00054cac82dfdd1621aa02d691dd1d08b9da536e61cccf411fc362937666323b3df646456'
}
dependencies {
implementation project(':unityLibrary')
}
android {
compileSdkVersion 34
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
signingConfigs {
release {
storePassword="REPLACE_PASSWORD"
keyPassword="REPLACE_PASSWORD"
keyAlias="juzu"
storeFile=file("../../keystore/dz_keystore.jks")
}
}
defaultConfig {
minSdkVersion 24
targetSdkVersion 34
applicationId 'REPLACE_APPLICATION_ID'
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
versionCode 1
versionName '0.1.0'
multiDexEnabled true
}
aaptOptions {
noCompress = ['.unity3d', '.ress', '.resource', '.obb', '.bundle', '.unityexp'] + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
lintOptions {
abortOnError false
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.release
jniDebuggable true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.release
}
}
packagingOptions {
doNotStrip '*/armeabi-v7a/*.so'
doNotStrip '*/arm64-v8a/*.so'
jniLibs {
useLegacyPackaging = true
}
}
bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = true
}
}
}

View File

@ -1,63 +1,29 @@
{
"project_info": {
"project_number": "1008416471093",
"project_id": "knights-combo",
"storage_bucket": "knights-combo.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:1008416471093:android:121c54160b7045e499d97c",
"android_client_info": {
"package_name": "com.combo.heroes.puzzle.rpg"
}
},
"oauth_client": [
{
"client_id": "1008416471093-e1a8gso0q6mpangmi7lltjilfmqeqp6u.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.combo.heroes.puzzle.rpg",
"certificate_hash": "3d9f0e5ebcb906418204e1a41cd40968a36c71cc"
}
},
{
"client_id": "1008416471093-eolgs4t98pog1q3oltg4vh726vpggqbd.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.combo.heroes.puzzle.rpg",
"certificate_hash": "dd7bea95dbb468b776ad9e979535689371113698"
}
},
{
"client_id": "1008416471093-e47s7u8a7v31ulr2f7e9j1mdm9llepum.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDtkUzjjkNiAZszdepIDIYss0ioNNbjncA"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "1008416471093-e47s7u8a7v31ulr2f7e9j1mdm9llepum.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "1008416471093-78jluae6d1tdl8l4qkul3hut7lckd1kc.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.combo.heroes.puzzle.rpg",
"app_store_id": "6450101181"
}
}
]
}
}
}
],
"configuration_version": "1"
{
"project_info": {
"project_number": "22951947163",
"project_id": "pull-pull-pull-heroes",
"storage_bucket": "pull-pull-pull-heroes.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:22951947163:android:378ebaf483bc3fb9304f3e",
"android_client_info": {
"package_name": "com.fortune.td.game.global"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAmIdtI6ZwxXfCVILmtZEr9y4CP_e9JpFE"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="REPLACE_APPLICATION_ID" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:extractNativeLibs="true" android:label="@string/app_name" android:icon="@mipmap/app_icon" android:roundIcon="@mipmap/app_icon_round" >
</application>
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="REPLACE_APPLICATION_ID" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:extractNativeLibs="true" android:label="@string/app_name" android:icon="@mipmap/app_icon" android:roundIcon="@mipmap/app_icon_round" >
</application>
</manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

After

Width:  |  Height:  |  Size: 710 B

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Combo de Jinetes</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Pull Pull Pull Heroes</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Ksatria Kombo</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Pull Pull Pull Heroes</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ナイト戦線</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">プルせよ!ヒーローズ</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">워리어 콤보</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">픽미픽미 영웅</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Cavaleiros do Combo</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Pull Pull Pull Heroes</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">อัศวินคอมโบ</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Pull Pull Pull Heroes</string>
</resources>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="BaseUnityTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen">
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="BaseUnityTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen">
</style>
</resources>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="BaseUnityTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen">
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="BaseUnityTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen">
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="FreeformWindowSize_maximize">maximize</string>
<string name="FreeformWindowSize_tablet">tablet</string>
<string name="FreeformWindowSize_phone">phone</string>
<string name="FreeformWindowOrientation_landscape">landscape</string>
<string name="FreeformWindowOrientation_portrait">portrait</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="FreeformWindowSize_maximize">maximize</string>
<string name="FreeformWindowSize_tablet">tablet</string>
<string name="FreeformWindowSize_phone">phone</string>
<string name="FreeformWindowOrientation_landscape">landscape</string>
<string name="FreeformWindowOrientation_portrait">portrait</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Kỵ Sĩ Liên Hoàn</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Phiêu Lưu Sinh Tồn - VTC Game</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">賽賽軍團</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">抽抽抽英雄</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">赛赛军团</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">抽抽抽英雄</string>
</resources>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="FreeformWindowSize_maximize"></string>
<string name="FreeformWindowSize_tablet"></string>
<string name="FreeformWindowSize_phone"></string>
<string name="FreeformWindowOrientation_landscape"></string>
<string name="FreeformWindowOrientation_portrait"></string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="FreeformWindowSize_maximize"></string>
<string name="FreeformWindowSize_tablet"></string>
<string name="FreeformWindowSize_phone"></string>
<string name="FreeformWindowOrientation_landscape"></string>
<string name="FreeformWindowOrientation_portrait"></string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="unitySurfaceView" />
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="unitySurfaceView" />
</resources>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Knights Combo</string>
<string name="game_view_content_description">Game view</string>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Pull Pull Pull Heroes</string>
<string name="game_view_content_description">Game view</string>
</resources>

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="UnityThemeSelector" parent="BaseUnityTheme">
<item name="android:windowBackground">@android:color/black</item>
</style>
<style name="BaseUnityTheme" parent="android:Theme.Holo.Light.NoActionBar.Fullscreen">
</style>
<style name="UnityThemeSelector.Translucent" parent="@style/UnityThemeSelector">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="UnityThemeSelector" parent="BaseUnityTheme">
<item name="android:windowBackground">@android:color/black</item>
</style>
<style name="BaseUnityTheme" parent="android:Theme.Holo.Light.NoActionBar.Fullscreen">
</style>
<style name="UnityThemeSelector.Translucent" parent="@style/UnityThemeSelector">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources>

View File

@ -1,44 +1,44 @@
package com.juzu.dz.message;
/**
* 管理和前端的通信消息以及json字段
* */
public class BFMessage {
// Google登录
public static final int GOOGLE_LOGIN_SUCCESS = 1;
public static final int GOOGLE_LOGIN_FAILED = 2;
// Google登出成功
public static final int GOOGLE_LOGOUT_SUCCESS = 3;
// Google支付
public static final int GOOGLE_PAY_SUCCESS = 4;
public static final int GOOGLE_PAY_FAILED = 5;
public static final int GOOGLE_PAY_CANCEL = 6;
public static final int GOOGLE_CONNECT_SUCCESS = 7;
public static final int GOOGLE_CONNECT_FAILED = 8;
public static final int QUERY_PRODUCT_SUCCESS = 9;
public static final int QUERY_PRODUCT_FAILED = 10;
public static final int QUERY_UNCOMPLETE_ORDER_FINISH = 11;
// Google消耗
public static final int GOOGLE_CONSUME_SUCCESS = 12;
public static final int GOOGLE_CONSUME_FAILED = 13;
// Google登出失败
public static final int GOOGLE_LOGOUT_FAILED = 14;
// fireBaseToken
public static final int FIREBASE_TOKEN = 15;
// Google订阅
public static final int QUERY_SUBSCRIBE_FINISH = 16;
// 显示全屏广告成功
public static final int ADMOB_SHOWED_FULLSCREEN = 17;
// 显示全屏广告失败
public static final int ADMOB_FAILEDTO_SHOW_FULLSCREEN = 18;
// 拒绝显示全屏广告
public static final int ADMOB_DISMISSED_FULLSCREEN = 19;
// 加载广告成功
public static final int ADMOB_LOADED = 20;
// 加载广告失败
public static final int ADMOB_LOADED_FAILED = 21;
// 获得奖励
public static final int ADMOB_EARNED_REWARD = 22;
// 初始化状态
public static final int ADMOB_INITIALIZED = 23;
}
package com.juzu.dz.message;
/**
* 管理和前端的通信消息以及json字段
* */
public class BFMessage {
// Google登录
public static final int GOOGLE_LOGIN_SUCCESS = 1;
public static final int GOOGLE_LOGIN_FAILED = 2;
// Google登出成功
public static final int GOOGLE_LOGOUT_SUCCESS = 3;
// Google支付
public static final int GOOGLE_PAY_SUCCESS = 4;
public static final int GOOGLE_PAY_FAILED = 5;
public static final int GOOGLE_PAY_CANCEL = 6;
public static final int GOOGLE_CONNECT_SUCCESS = 7;
public static final int GOOGLE_CONNECT_FAILED = 8;
public static final int QUERY_PRODUCT_SUCCESS = 9;
public static final int QUERY_PRODUCT_FAILED = 10;
public static final int QUERY_UNCOMPLETE_ORDER_FINISH = 11;
// Google消耗
public static final int GOOGLE_CONSUME_SUCCESS = 12;
public static final int GOOGLE_CONSUME_FAILED = 13;
// Google登出失败
public static final int GOOGLE_LOGOUT_FAILED = 14;
// fireBaseToken
public static final int FIREBASE_TOKEN = 15;
// Google订阅
public static final int QUERY_SUBSCRIBE_FINISH = 16;
// 显示全屏广告成功
public static final int ADMOB_SHOWED_FULLSCREEN = 17;
// 显示全屏广告失败
public static final int ADMOB_FAILEDTO_SHOW_FULLSCREEN = 18;
// 拒绝显示全屏广告
public static final int ADMOB_DISMISSED_FULLSCREEN = 19;
// 加载广告成功
public static final int ADMOB_LOADED = 20;
// 加载广告失败
public static final int ADMOB_LOADED_FAILED = 21;
// 获得奖励
public static final int ADMOB_EARNED_REWARD = 22;
// 初始化状态
public static final int ADMOB_INITIALIZED = 23;
}

View File

@ -1,50 +1,50 @@
package com.juzu.dz.third;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class BFFirebaseMessagingService extends FirebaseMessagingService {
/**
* 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 onMessageReceived(RemoteMessage remoteMessage) {
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());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d("TAG", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
@Override
public void onNewToken(String token) {
Log.d("", "Refreshed token: " + token);
sendRegistrationToServer(token);
}
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
}
}
package com.juzu.dz.third;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class BFFirebaseMessagingService extends FirebaseMessagingService {
/**
* 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 onMessageReceived(RemoteMessage remoteMessage) {
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());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d("TAG", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
@Override
public void onNewToken(String token) {
Log.d("", "Refreshed token: " + token);
sendRegistrationToServer(token);
}
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
}
}

View File

@ -1,291 +1,302 @@
// package com.juzu.dz.third;
// import android.app.Activity;
// import android.content.Intent;
// import android.os.Bundle;
// import android.util.Log;
// import androidx.annotation.NonNull;
// import com.google.android.gms.ads.AdError;
// import com.google.android.gms.ads.AdRequest;
// import com.google.android.gms.ads.AdValue;
// import com.google.android.gms.ads.AdapterResponseInfo;
// import com.google.android.gms.ads.FullScreenContentCallback;
// import com.google.android.gms.ads.LoadAdError;
// import com.google.android.gms.ads.MobileAds;
// import com.google.android.gms.ads.OnPaidEventListener;
// import com.google.android.gms.ads.OnUserEarnedRewardListener;
// import com.google.android.gms.ads.ResponseInfo;
// import com.google.android.gms.ads.initialization.AdapterStatus;
// import com.google.android.gms.ads.initialization.InitializationStatus;
// import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
// import com.google.android.gms.ads.rewarded.RewardItem;
// import com.google.android.gms.ads.rewarded.RewardedAd;
// import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
// import com.juzu.dz.message.BFMessage;
// import java.util.Map;
// public class GoogleAdmobRewardedVideo {
// private final String AD_UNIT_ID = "ca-app-pub-1136292565368915/9438857158";
// private final String LOG_TAG = "RewardedVideo";
// private static volatile GoogleAdmobRewardedVideo sInstance;
// private RewardedAd rewardedAd;
// private String adPlacement = "";
// private boolean isLoading = false;
// public static GoogleAdmobRewardedVideo getInstance()
// {
// if (sInstance == null) {
// synchronized (GoogleLogin.class) {
// if (sInstance == null) {
// sInstance = new GoogleAdmobRewardedVideo();
// }
// }
// }
// return sInstance;
// }
// public void init(Activity activity){
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "01");
// GooglePlugin.logEventBundle("admob_sdk_init_start", bundle);
// MobileAds.initialize(activity, new OnInitializationCompleteListener() {
// @Override
// public void onInitializationComplete(InitializationStatus initializationStatus) {
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_INITIALIZED, "");
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "02");
// GooglePlugin.logEventBundle("admob_sdk_init_complete", bundle);
// // loadRewardedAd(activity);
// }
// });
// loadRewardedAd(activity);
// }
// private void pauseGame() {
// }
// private void resumeGame() {
// }
// private void loadRewardedAd(Activity activity) {
// if (isLoading)
// {
// return;
// }
// if (rewardedAd == null) {
// isLoading = true;
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "03");
// bundle.putString("ad_placement", adPlacement);
// GooglePlugin.logEventBundle("admob_ad_request", bundle);
// AdRequest adRequest = new AdRequest.Builder().build();
// activity.runOnUiThread(new Runnable() {
// public void run() {
// RewardedAd.load(
// activity,
// AD_UNIT_ID,
// adRequest,
// new RewardedAdLoadCallback() {
// @Override
// public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
// // Handle the error.
// Log.w(LOG_TAG, "loadAdError:" + loadAdError.getMessage());
// rewardedAd = null;
// isLoading = false;
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_LOADED_FAILED, "");
// // Toast.makeText(_activity.this, "onAdFailedToLoad", Toast.LENGTH_SHORT).show();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "05");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("error_code", "" + loadAdError.getCode());
// GooglePlugin.logEventBundle("admob_ad_load_fail", bundle);
// }
// @Override
// public void onAdLoaded(@NonNull RewardedAd newRewardedAd) {
// Log.w(LOG_TAG, "onAdLoaded");
// rewardedAd = newRewardedAd;
// isLoading = false;
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_LOADED, "");
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "04");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_ad_load_success", bundle);
// }
// }
// // Toast.makeText(_activity.this, "onAdLoaded", Toast.LENGTH_SHORT).show();
// }
// });
// }
// });
// }
// }
// private void showRewardedVideo(Activity activity) {
// if (rewardedAd == null) {
// Log.w(LOG_TAG, "The rewarded ad wasn't ready yet.");
// return;
// }
// activity.runOnUiThread(new Runnable() {
// public void run() {
// rewardedAd.setOnPaidEventListener(
// new OnPaidEventListener() {
// @Override
// public void onPaidEvent(@NonNull AdValue adValue) {
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "10");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putDouble("ad_value", adValue.getValueMicros());
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_ad_open_success", bundle);
// }
// }
// }
// }
// );
// rewardedAd.setFullScreenContentCallback(
// new FullScreenContentCallback() {
// @Override
// public void onAdShowedFullScreenContent() {
// // Called when ad is shown.
// Log.w(LOG_TAG, "onAdShowedFullScreenContent");
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_SHOWED_FULLSCREEN, "");
// }
// @Override
// public void onAdFailedToShowFullScreenContent(AdError adError) {
// // Called when ad fails to show.
// Log.w(LOG_TAG, "onAdFailedToShowFullScreenContent");
// // Don't forget to set the ad reference to null so you
// // don't show the ad a second time.
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "11");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// bundle.putString("error_code", "" + adError.getCode());
// GooglePlugin.logEventBundle("admob_ad_open_fail", bundle);
// }
// }
// rewardedAd = null;
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_FAILEDTO_SHOW_FULLSCREEN, "");
// adPlacement = "";
// }
// @Override
// public void onAdDismissedFullScreenContent() {
// // Called when ad is dismissed.
// // Don't forget to set the ad reference to null so you
// // don't show the ad a second time.
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "12");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_ad_close", bundle);
// }
// }
// rewardedAd = null;
// Log.w(LOG_TAG, "onAdDismissedFullScreenContent");
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_DISMISSED_FULLSCREEN, "");
// }
// });
// Activity activityContext = activity;
// rewardedAd.show(
// activityContext,
// new OnUserEarnedRewardListener() {
// @Override
// public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
// // Handle the reward.
// Log.w(LOG_TAG, "The user earned the reward.");
// // int rewardAmount = rewardItem.getAmount();
// // String rewardType = rewardItem.getType();
// // Log.w(LOG_TAG, "onUserEarnedReward rewardAmount = " + rewardAmount);
// // Log.w(LOG_TAG, "onUserEarnedReward rewardType = " + rewardType);
// // JSONObject json = new JSONObject();
// // json.put("status", 0);
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_EARNED_REWARD, "");
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "13");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_reward_earn", bundle);
// }
// }
// adPlacement = "";
// }
// });
// }
// });
// }
// public void showFullScreenAds(Activity activity) {
// showRewardedVideo(activity);
// }
// public void tryLoadRewardedAd(Activity activity)
// {
// loadRewardedAd(activity);
// }
// public void setAdPlacement(String placement)
// {
// adPlacement = placement;
// }
// package com.juzu.dz.third;
// import android.app.Activity;
// import android.content.Intent;
// import android.os.Bundle;
// import android.util.Log;
// import androidx.annotation.NonNull;
// import com.google.android.gms.ads.AdError;
// import com.google.android.gms.ads.AdRequest;
// import com.google.android.gms.ads.AdValue;
// import com.google.android.gms.ads.AdapterResponseInfo;
// import com.google.android.gms.ads.FullScreenContentCallback;
// import com.google.android.gms.ads.LoadAdError;
// import com.google.android.gms.ads.MobileAds;
// import com.google.android.gms.ads.OnPaidEventListener;
// import com.google.android.gms.ads.OnUserEarnedRewardListener;
// import com.google.android.gms.ads.ResponseInfo;
// import com.google.android.gms.ads.initialization.AdapterStatus;
// import com.google.android.gms.ads.initialization.InitializationStatus;
// import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
// import com.google.android.gms.ads.rewarded.RewardItem;
// import com.google.android.gms.ads.rewarded.RewardedAd;
// import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
// import com.juzu.dz.message.BFMessage;
// import java.util.Map;
// public class GoogleAdmobRewardedVideo {
// // 这是b2的id不能直接用
// // private final String AD_UNIT_ID = "ca-app-pub-1136292565368915/9438857158";
// private final String AD_UNIT_ID = "";
// private final String LOG_TAG = "RewardedVideo";
// private static volatile GoogleAdmobRewardedVideo sInstance;
// private RewardedAd rewardedAd;
// private String adPlacement = "";
// boolean isLoading;
// public static GoogleAdmobRewardedVideo getInstance()
// {
// if (sInstance == null) {
// synchronized (GoogleLogin.class) {
// if (sInstance == null) {
// sInstance = new GoogleAdmobRewardedVideo();
// }
// }
// }
// return sInstance;
// }
// public void init(Activity activity){
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "01");
// GooglePlugin.logEventBundle("admob_sdk_init_start", bundle);
// MobileAds.initialize(activity, new OnInitializationCompleteListener() {
// @Override
// public void onInitializationComplete(InitializationStatus initializationStatus) {
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_INITIALIZED, "");
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "02");
// GooglePlugin.logEventBundle("admob_sdk_init_complete", bundle);
// // loadRewardedAd(activity);
// }
// });
// loadRewardedAd(activity);
// // startGame(activity);
// }
// private void pauseGame() {
// }
// private void resumeGame() {
// }
// private void loadRewardedAd(Activity activity) {
// if (rewardedAd == null) {
// isLoading = true;
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "03");
// bundle.putString("ad_placement", adPlacement);
// GooglePlugin.logEventBundle("admob_ad_request", bundle);
// AdRequest adRequest = new AdRequest.Builder().build();
// activity.runOnUiThread(new Runnable() {
// public void run() {
// RewardedAd.load(
// activity,
// AD_UNIT_ID,
// adRequest,
// new RewardedAdLoadCallback() {
// @Override
// public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
// // Handle the error.
// Log.w("RewardedVideo", loadAdError.getMessage());
// rewardedAd = null;
// isLoading = false;
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_LOADED_FAILED, "");
// // Toast.makeText(_activity.this, "onAdFailedToLoad", Toast.LENGTH_SHORT).show();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "05");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("error_code", "" + loadAdError.getCode());
// GooglePlugin.logEventBundle("admob_ad_load_fail", bundle);
// }
// @Override
// public void onAdLoaded(@NonNull RewardedAd newRewardedAd) {
// Log.w("RewardedVideo", "onAdLoaded");
// rewardedAd = newRewardedAd;
// isLoading = false;
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_LOADED, "");
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "04");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_ad_load_success", bundle);
// }
// }
// // Toast.makeText(_activity.this, "onAdLoaded", Toast.LENGTH_SHORT).show();
// }
// });
// }
// });
// }
// }
// // private void startGame(Activity activity) {
// // Hide the retry button, load the ad, and start the timer.
// // if (rewardedAd != null && !isLoading) {
// // loadRewardedAd(activity);
// // }
// // createTimer(COUNTER_TIME);
// // gamePaused = false;
// // gameOver = false;
// // }
// private void showRewardedVideo(Activity activity) {
// if (rewardedAd == null) {
// Log.w("TAG", "The rewarded ad wasn't ready yet.");
// return;
// }
// activity.runOnUiThread(new Runnable() {
// public void run() {
// rewardedAd.setOnPaidEventListener(
// new OnPaidEventListener() {
// @Override
// public void onPaidEvent(@NonNull AdValue adValue) {
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "10");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putDouble("ad_value", adValue.getValueMicros());
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_ad_open_success", bundle);
// }
// }
// }
// }
// );
// rewardedAd.setFullScreenContentCallback(
// new FullScreenContentCallback() {
// @Override
// public void onAdShowedFullScreenContent() {
// // Called when ad is shown.
// Log.w(LOG_TAG, "onAdShowedFullScreenContent");
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_SHOWED_FULLSCREEN, "");
// }
// @Override
// public void onAdFailedToShowFullScreenContent(AdError adError) {
// // Called when ad fails to show.
// Log.w(LOG_TAG, "onAdFailedToShowFullScreenContent");
// // Don't forget to set the ad reference to null so you
// // don't show the ad a second time.
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "11");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// bundle.putString("error_code", "" + adError.getCode());
// GooglePlugin.logEventBundle("admob_ad_open_fail", bundle);
// }
// }
// rewardedAd = null;
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_FAILEDTO_SHOW_FULLSCREEN, "");
// adPlacement = "";
// }
// @Override
// public void onAdDismissedFullScreenContent() {
// // Called when ad is dismissed.
// // Don't forget to set the ad reference to null so you
// // don't show the ad a second time.
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "12");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_ad_close", bundle);
// }
// }
// rewardedAd = null;
// Log.w(LOG_TAG, "onAdDismissedFullScreenContent");
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_DISMISSED_FULLSCREEN, "");
// }
// });
// Activity activityContext = activity;
// rewardedAd.show(
// activityContext,
// new OnUserEarnedRewardListener() {
// @Override
// public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
// // Handle the reward.
// Log.w("TAG", "The user earned the reward.");
// int rewardAmount = rewardItem.getAmount();
// String rewardType = rewardItem.getType();
// Log.w(LOG_TAG, "onUserEarnedReward rewardAmount = " + rewardAmount);
// Log.w(LOG_TAG, "onUserEarnedReward rewardType = " + rewardType);
// // JSONObject json = new JSONObject();
// // json.put("status", 0);
// GooglePlugin.sendMessageToUnity(BFMessage.ADMOB_EARNED_REWARD, "");
// ResponseInfo responseInfo = rewardedAd.getResponseInfo();
// if (responseInfo != null)
// {
// AdapterResponseInfo loadedAdapterResponseInfo = responseInfo.getLoadedAdapterResponseInfo();
// if (loadedAdapterResponseInfo != null)
// {
// String adSourceName = loadedAdapterResponseInfo.getAdSourceName();
// Bundle bundle = new Bundle();
// bundle.putString("flow_seq", "13");
// bundle.putString("ad_placement", adPlacement);
// bundle.putString("ad_source", adSourceName);
// bundle.putString("ad_response_id", responseInfo.getResponseId());
// GooglePlugin.logEventBundle("admob_reward_earn", bundle);
// }
// }
// adPlacement = "";
// }
// });
// }
// });
// }
// public void showFullScreenAds(Activity activity) {
// Log.w(LOG_TAG, "showFullScreenAds");
// showRewardedVideo(activity);
// }
// public void tryLoadRewardedAd(Activity activity)
// {
// loadRewardedAd(activity);
// }
// public void setAdPlacement(String placement)
// {
// adPlacement = placement;
// }
// }

View File

@ -1,459 +1,459 @@
package com.juzu.dz.third;
import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.billingclient.api.AccountIdentifiers;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
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.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import com.juzu.dz.message.BFMessage;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GoogleBilling {
private static volatile GoogleBilling sInstance;
private static final String LOG_TAG = "GoogleBilling";
private static BillingClient mGoogleBillingClient;
private Map<String, Purchase> mPurchase = new HashMap<String, Purchase>();
private List<SkuDetails> mSubList = new ArrayList<SkuDetails>();
private List<SkuDetails> mInAppList = new ArrayList<SkuDetails>();
final private static String BASE_64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq3fn02CUbrnNkF1PYXk1XHuJdJsnUMsUHXaYR83+ZPE2a3NgGHpVsrVakZK28RARQSz8E2x8qy+4bFPji1TTLq+MRY9CAcGzP4HB5eGKhRmsHABJNnfWgMiXxZ/mmW/yQawTY0zmeDX6Z/GSN3SeZo0PmlpM7ZFJpN42vYO6Fs5zgR05SAUDx3uaPwkhZ0Z2bIIhbWaVyxoMy2pDnCfCL5ym1nwdDa8tRMhZ1yWaDdY4KkJ92W0kbyMntjtL9QWFCGcRTGHVEoir4E2nc2bugaOkw0qegng00L65qWnfZ1GFgPW3uNexWsbEc2A5g//bL2/+yDVQWqiJtkdQMKyIKwIDAQAB";
public static GoogleBilling getInstance()
{
if (sInstance == null) {
synchronized (GoogleBilling.class) {
if (sInstance == null) {
sInstance = new GoogleBilling();
}
}
}
return sInstance;
}
public void init(Activity activity){
mGoogleBillingClient = BillingClient.newBuilder(activity).setListener(payListener).enablePendingPurchases().build();
connectGoogleStore();
}
public void connectGoogleStore(){
mGoogleBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_SUCCESS, "");
}else{
String msg = billingResult.getDebugMessage();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, msg);
}
}
@Override
public void onBillingServiceDisconnected() {
String msg = "disconnected";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, msg);
}
});
}
// 查询商品信息本地化用
public void queryProductsInfo(String payType, String productInfoJson){
Log.d(LOG_TAG, "google queryProductsInfo info from unity:" + productInfoJson);
try {
JSONArray array = new JSONArray(productInfoJson);
String[] proList = new String[array.length()];
for (int i = 0; i < array.length(); i++){
proList[i] = (String)array.get(i);
}
queryProducts(payType, proList);
} catch (JSONException e) {
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, e.toString());
}
}
//通过商品id查询商品详情
private void queryProducts(String payType, String [] products){
List<String> pList = Arrays.asList(products);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(pList).setType(payType);
mGoogleBillingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> list) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null){
Log.d(LOG_TAG, "queryProducts success count:" + list.size());
if (list.size() == 0){
String msg = "未查询到商品信息,请检查传入的商品id,或者配置是否生效";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, msg);
return;
}
JSONArray array = new JSONArray();
List<SkuDetails> mList = new ArrayList<SkuDetails>();
for (SkuDetails skuDetails : list) {
mList.add(skuDetails);
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();//实际价格
String originPrice = skuDetails.getOriginalPrice();//原价如果没折扣原价=实际价格
String description = skuDetails.getDescription();
String originalJson = skuDetails.getOriginalJson();
String title = skuDetails.getTitle();
String priceAmountMicros = String.valueOf(skuDetails.getPriceAmountMicros());
String currencyCode = skuDetails.getPriceCurrencyCode();
JSONObject info = new JSONObject();
try {
info.put("sku", sku);
info.put("price", price);
info.put("originPrice", originPrice);
info.put("description", description);
info.put("originalJson", originalJson);
info.put("title", title);
info.put("priceCurrencyCode", currencyCode);
info.put("priceAmountMicros", priceAmountMicros);
} catch (JSONException e) {
e.printStackTrace();
}
array.put(info);
}
if(payType.equals(BillingClient.SkuType.INAPP)){
mInAppList = mList;
}
if(payType.equals(BillingClient.SkuType.SUBS)){
mSubList = mList;
}
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_SUCCESS, array.toString());
}else{
String msg = "queryProducts error:" + billingResult.getResponseCode();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, msg);
}
}
});
}
// 支付
public void pay(Activity activity, String payType, String productId, String customMsg){
List<SkuDetails> skuList = null;
if(payType.equals(BillingClient.SkuType.INAPP)){
skuList = mInAppList;
}
if(payType.equals(BillingClient.SkuType.SUBS)){
skuList = mSubList;
}
if (skuList == null || skuList.size() == 0){
String msg = "no sku";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
return ;
}
SkuDetails paySku = null;
for (SkuDetails details:skuList){
if (TextUtils.equals(productId, details.getSku())){
paySku = details;
break;
}
}
if (paySku == null){
String msg = "sku not found! please contact developer";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
return;
}
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(paySku)
.setObfuscatedAccountId(customMsg)
.build();
BillingResult result = mGoogleBillingClient.launchBillingFlow(activity, flowParams);
if (result.getResponseCode() != BillingClient.BillingResponseCode.OK){
String msg = "Billing failed: + " + result.getDebugMessage();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
}
private PurchasesUpdatedListener payListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
switch (billingResult.getResponseCode()) {
case BillingClient.BillingResponseCode.OK:
if (null != purchases) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else {
String msg = "Null Purchase List Returned from OK response!";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
break;
case BillingClient.BillingResponseCode.USER_CANCELED:
Log.i(LOG_TAG, "onPurchasesUpdated: User canceled the purchase");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_CANCEL, "");
break;
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
String msg = "onPurchasesUpdated: The user already owns this item";
Log.i(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
break;
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
String msg2 = "onPurchasesUpdated: 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.";
Log.e(LOG_TAG, msg2);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg2);
break;
default:
String msg3 = "BillingResult [" + billingResult.getResponseCode() + "]: " + billingResult.getDebugMessage();
Log.d(LOG_TAG, msg3);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg3);
}
}
};
private void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
// 支付完成
if(!purchase.isAcknowledged()){
mPurchase.put(purchase.getPurchaseToken(),purchase);
}
//验证签名
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
boolean succ = verifyValidSignature(originalJson, signature);
JSONObject productInfo = new JSONObject();
try {
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
productInfo.put("signtureFlag", succ + "");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_SUCCESS, productInfo.toString());
}else{
//未付款
String msg = "purchase.getPurchaseState() != Purchase.PurchaseState.PURCHASED";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
}
//消耗
public void consumeAsync(String purchaseToken){
Purchase purchase = mPurchase.get(purchaseToken);
boolean isSub = false;
if(purchase != null){
if(mSubList != null){
for(SkuDetails Sku:mSubList){
for ( String purchaseSku : purchase.getSkus() ) {
if (purchaseSku.equals(Sku.getSku())) {
isSub = true;
break;
}
}
}
}
}
if(isSub){
handleSubsPurchase(purchase);
}else{
final ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken)
.build();
mGoogleBillingClient.consumeAsync(consumeParams, (billingResult, purchaseToken1) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "消耗成功...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_SUCCESS, "");
} else {
Log.d(LOG_TAG, "消耗失败...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "");
}
});
}
}
private void handleSubsPurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken())
.build();
mGoogleBillingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {
@Override
public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "订阅成功...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_SUCCESS, "");
} else {
Log.d(LOG_TAG, "订阅失败...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "");
}
}
});
}
}
}
//查询缓存的购买交易
public void queryUncompleteOrder(String payType){
if (mGoogleBillingClient == null){
String msg = "queryPurchases billingClient is null";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
return;
}
mGoogleBillingClient.queryPurchasesAsync(payType, (billingResult, list) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "Billing client was null or result code is:" + billingResult.getDebugMessage());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
} else {
//消耗
JSONArray jsonArray = new JSONArray();
for (Purchase purchase : list){
//商品购买成功系统还会生成购买令牌它是一个唯一标识符表示用户及其所购应用内商品的商品 I
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()){
mPurchase.put(purchase.getPurchaseToken(), purchase);
//验证签名
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("payType", payType);
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
boolean succ = verifyValidSignature(originalJson,signature);
productInfo.put("signtureFlag", String.valueOf(succ));
productInfo.put("purchaseState", "1");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING){
ArrayList<String> skus = purchase.getSkus();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("purchaseState", "2");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, jsonArray.toString());
}
});
}
//查询缓存的訂閲状态
public void querySubscribeOrder(String payType) {
if (mGoogleBillingClient == null) {
String msg = "queryPurchases billingClient is null";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
return;
}
mGoogleBillingClient.queryPurchasesAsync(payType, (billingResult, list) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "Billing client was null or result code is:" + billingResult.getDebugMessage());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
} else {
//消耗
JSONArray jsonArray = new JSONArray();
for (Purchase purchase : list){
//商品购买成功系统还会生成购买令牌它是一个唯一标识符表示用户及其所购应用内商品的商品 I
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("payType", payType);
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
boolean succ = verifyValidSignature(originalJson,signature);
productInfo.put("signtureFlag", String.valueOf(succ));
productInfo.put("purchaseState", "1");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}
Log.d(LOG_TAG, "订阅状态查询 " + jsonArray.toString());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, jsonArray.toString());
}
});
}
private boolean verifyValidSignature(String signedData, String signature) {
return Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature);
}
public void onDestroy(){
if (mGoogleBillingClient != null && mGoogleBillingClient.isReady()){
mGoogleBillingClient.endConnection();
mGoogleBillingClient = null;
}
}
}
package com.juzu.dz.third;
import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.billingclient.api.AccountIdentifiers;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
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.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import com.juzu.dz.message.BFMessage;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GoogleBilling {
private static volatile GoogleBilling sInstance;
private static final String LOG_TAG = "GoogleBilling";
private static BillingClient mGoogleBillingClient;
private Map<String, Purchase> mPurchase = new HashMap<String, Purchase>();
private List<SkuDetails> mSubList = new ArrayList<SkuDetails>();
private List<SkuDetails> mInAppList = new ArrayList<SkuDetails>();
final private static String BASE_64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtIC/9macCZdKcRamY6XOf+J+ncHwUzrRx18696PPH0kixqIAovJKAISUeZCH28NTBb/t4dwgnPRMjNsviH71BVDOK7ZSm2xkbhi4aQ8lB5afGso9nj0+RaaONQeHMW17sIkqd2DIjiMWlPwt65pdonwXZ4NqQJwNabXMhzHggI9fjHH9mJodqqrKkwwIQtFyDe6OYC9kv6DIHhsVVDTfwKbq5QLJEHnsJKJbhuemI0aN6qwSf8tUxLWRJN+P6g88+tfRo5mI7A+slLdcom8Yf+OSQoXGPQJ6xplrfABTB1V7JymfiZg7JHLql65SwG6zk/GFAD0VcIWTfeogvyElkQIDAQAB";
public static GoogleBilling getInstance()
{
if (sInstance == null) {
synchronized (GoogleBilling.class) {
if (sInstance == null) {
sInstance = new GoogleBilling();
}
}
}
return sInstance;
}
public void init(Activity activity){
mGoogleBillingClient = BillingClient.newBuilder(activity).setListener(payListener).enablePendingPurchases().build();
connectGoogleStore();
}
public void connectGoogleStore(){
mGoogleBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_SUCCESS, "");
}else{
String msg = billingResult.getDebugMessage();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, msg);
}
}
@Override
public void onBillingServiceDisconnected() {
String msg = "disconnected";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, msg);
}
});
}
// 查询商品信息本地化用
public void queryProductsInfo(String payType, String productInfoJson){
Log.d(LOG_TAG, "google queryProductsInfo info from unity:" + productInfoJson);
try {
JSONArray array = new JSONArray(productInfoJson);
String[] proList = new String[array.length()];
for (int i = 0; i < array.length(); i++){
proList[i] = (String)array.get(i);
}
queryProducts(payType, proList);
} catch (JSONException e) {
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, e.toString());
}
}
//通过商品id查询商品详情
private void queryProducts(String payType, String [] products){
List<String> pList = Arrays.asList(products);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(pList).setType(payType);
mGoogleBillingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> list) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null){
Log.d(LOG_TAG, "queryProducts success count:" + list.size());
if (list.size() == 0){
String msg = "未查询到商品信息,请检查传入的商品id,或者配置是否生效";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, msg);
return;
}
JSONArray array = new JSONArray();
List<SkuDetails> mList = new ArrayList<SkuDetails>();
for (SkuDetails skuDetails : list) {
mList.add(skuDetails);
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();//实际价格
String originPrice = skuDetails.getOriginalPrice();//原价如果没折扣原价=实际价格
String description = skuDetails.getDescription();
String originalJson = skuDetails.getOriginalJson();
String title = skuDetails.getTitle();
String priceAmountMicros = String.valueOf(skuDetails.getPriceAmountMicros());
String currencyCode = skuDetails.getPriceCurrencyCode();
JSONObject info = new JSONObject();
try {
info.put("sku", sku);
info.put("price", price);
info.put("originPrice", originPrice);
info.put("description", description);
info.put("originalJson", originalJson);
info.put("title", title);
info.put("priceCurrencyCode", currencyCode);
info.put("priceAmountMicros", priceAmountMicros);
} catch (JSONException e) {
e.printStackTrace();
}
array.put(info);
}
if(payType.equals(BillingClient.SkuType.INAPP)){
mInAppList = mList;
}
if(payType.equals(BillingClient.SkuType.SUBS)){
mSubList = mList;
}
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_SUCCESS, array.toString());
}else{
String msg = "queryProducts error:" + billingResult.getResponseCode();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, msg);
}
}
});
}
// 支付
public void pay(Activity activity, String payType, String productId, String customMsg){
List<SkuDetails> skuList = null;
if(payType.equals(BillingClient.SkuType.INAPP)){
skuList = mInAppList;
}
if(payType.equals(BillingClient.SkuType.SUBS)){
skuList = mSubList;
}
if (skuList == null || skuList.size() == 0){
String msg = "no sku";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
return ;
}
SkuDetails paySku = null;
for (SkuDetails details:skuList){
if (TextUtils.equals(productId, details.getSku())){
paySku = details;
break;
}
}
if (paySku == null){
String msg = "sku not found! please contact developer";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
return;
}
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(paySku)
.setObfuscatedAccountId(customMsg)
.build();
BillingResult result = mGoogleBillingClient.launchBillingFlow(activity, flowParams);
if (result.getResponseCode() != BillingClient.BillingResponseCode.OK){
String msg = "Billing failed: + " + result.getDebugMessage();
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
}
private PurchasesUpdatedListener payListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
switch (billingResult.getResponseCode()) {
case BillingClient.BillingResponseCode.OK:
if (null != purchases) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else {
String msg = "Null Purchase List Returned from OK response!";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
break;
case BillingClient.BillingResponseCode.USER_CANCELED:
Log.i(LOG_TAG, "onPurchasesUpdated: User canceled the purchase");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_CANCEL, "");
break;
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
String msg = "onPurchasesUpdated: The user already owns this item";
Log.i(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
break;
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
String msg2 = "onPurchasesUpdated: 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.";
Log.e(LOG_TAG, msg2);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg2);
break;
default:
String msg3 = "BillingResult [" + billingResult.getResponseCode() + "]: " + billingResult.getDebugMessage();
Log.d(LOG_TAG, msg3);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg3);
}
}
};
private void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
// 支付完成
if(!purchase.isAcknowledged()){
mPurchase.put(purchase.getPurchaseToken(),purchase);
}
//验证签名
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
boolean succ = verifyValidSignature(originalJson, signature);
JSONObject productInfo = new JSONObject();
try {
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
productInfo.put("signtureFlag", succ + "");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_SUCCESS, productInfo.toString());
}else{
//未付款
String msg = "purchase.getPurchaseState() != Purchase.PurchaseState.PURCHASED";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, msg);
}
}
//消耗
public void consumeAsync(String purchaseToken){
Purchase purchase = mPurchase.get(purchaseToken);
boolean isSub = false;
if(purchase != null){
if(mSubList != null){
for(SkuDetails Sku:mSubList){
for ( String purchaseSku : purchase.getSkus() ) {
if (purchaseSku.equals(Sku.getSku())) {
isSub = true;
break;
}
}
}
}
}
if(isSub){
handleSubsPurchase(purchase);
}else{
final ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken)
.build();
mGoogleBillingClient.consumeAsync(consumeParams, (billingResult, purchaseToken1) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "消耗成功...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_SUCCESS, "");
} else {
Log.d(LOG_TAG, "消耗失败...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "");
}
});
}
}
private void handleSubsPurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken())
.build();
mGoogleBillingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {
@Override
public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "订阅成功...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_SUCCESS, "");
} else {
Log.d(LOG_TAG, "订阅失败...");
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "");
}
}
});
}
}
}
//查询缓存的购买交易
public void queryUncompleteOrder(String payType){
if (mGoogleBillingClient == null){
String msg = "queryPurchases billingClient is null";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
return;
}
mGoogleBillingClient.queryPurchasesAsync(payType, (billingResult, list) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "Billing client was null or result code is:" + billingResult.getDebugMessage());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
} else {
//消耗
JSONArray jsonArray = new JSONArray();
for (Purchase purchase : list){
//商品购买成功系统还会生成购买令牌它是一个唯一标识符表示用户及其所购应用内商品的商品 I
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()){
mPurchase.put(purchase.getPurchaseToken(), purchase);
//验证签名
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("payType", payType);
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
boolean succ = verifyValidSignature(originalJson,signature);
productInfo.put("signtureFlag", String.valueOf(succ));
productInfo.put("purchaseState", "1");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING){
ArrayList<String> skus = purchase.getSkus();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("purchaseState", "2");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, jsonArray.toString());
}
});
}
//查询缓存的訂閲状态
public void querySubscribeOrder(String payType) {
if (mGoogleBillingClient == null) {
String msg = "queryPurchases billingClient is null";
Log.d(LOG_TAG, msg);
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
return;
}
mGoogleBillingClient.queryPurchasesAsync(payType, (billingResult, list) -> {
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
Log.d(LOG_TAG, "Billing client was null or result code is:" + billingResult.getDebugMessage());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
} else {
//消耗
JSONArray jsonArray = new JSONArray();
for (Purchase purchase : list){
//商品购买成功系统还会生成购买令牌它是一个唯一标识符表示用户及其所购应用内商品的商品 I
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
String orderId = purchase.getOrderId();
String originalJson = purchase.getOriginalJson();
String purchaseToken = purchase.getPurchaseToken();
ArrayList<String> skus = purchase.getSkus();
String signature = purchase.getSignature();
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
String obfuscatedAccountId = accountIdentifiers.getObfuscatedAccountId();
JSONObject productInfo = new JSONObject();
try {
productInfo.put("payType", payType);
productInfo.put("orderId", orderId);
productInfo.put("purchaseToken", purchaseToken);
productInfo.put("obfuscatedAccountId", obfuscatedAccountId);
boolean succ = verifyValidSignature(originalJson,signature);
productInfo.put("signtureFlag", String.valueOf(succ));
productInfo.put("purchaseState", "1");
if (skus.size() > 0)
{
productInfo.put("productId", skus.get(0));
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(productInfo);
}
}
Log.d(LOG_TAG, "订阅状态查询 " + jsonArray.toString());
GooglePlugin.sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, jsonArray.toString());
}
});
}
private boolean verifyValidSignature(String signedData, String signature) {
return Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature);
}
public void onDestroy(){
if (mGoogleBillingClient != null && mGoogleBillingClient.isReady()){
mGoogleBillingClient.endConnection();
mGoogleBillingClient = null;
}
}
}

View File

@ -1,97 +1,98 @@
package com.juzu.dz.third;
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.NonNull;
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.ApiException;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import org.json.JSONException;
import org.json.JSONObject;
import com.juzu.dz.message.BFMessage;
public class GoogleLogin {
private static volatile GoogleLogin sInstance;
private GoogleSignInClient mGoogleSignInClient;
private static final int REQUEST_CODE_GOOGLE_SIGN_IN = 1001; /* unique request id */
private static final String server_client_token = "1008416471093-e47s7u8a7v31ulr2f7e9j1mdm9llepum.apps.googleusercontent.com";
public static GoogleLogin getInstance()
{
if (sInstance == null) {
synchronized (GoogleLogin.class) {
if (sInstance == null) {
sInstance = new GoogleLogin();
}
}
}
return sInstance;
}
public void init(Activity activity){
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestId()
.requestIdToken(server_client_token)
.requestServerAuthCode(server_client_token)
.requestScopes(new Scope(Scopes.PLUS_ME))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(activity, gso);
}
public void login(Activity activity)
{
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
activity.startActivityForResult(signInIntent, REQUEST_CODE_GOOGLE_SIGN_IN);
}
public void logout(Activity activity)
{
mGoogleSignInClient.signOut().addOnCompleteListener(activity, new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGOUT_SUCCESS, "");
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_CODE_GOOGLE_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGIN_SUCCESS, createLoginInfo(account));
} catch (ApiException e) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGIN_FAILED, "google login failed e:" + e.getStatusCode() + " msg:" + e.getMessage());
}
}
private String createLoginInfo(GoogleSignInAccount account){
String idToken = account.getIdToken();
String uid = account.getId();
JSONObject result = new JSONObject();
try {
result.put("Token", idToken);
result.put("UserId", uid);
} catch (JSONException e) {
e.printStackTrace();
}
return result.toString();
}
}
package com.juzu.dz.third;
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.NonNull;
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.ApiException;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import org.json.JSONException;
import org.json.JSONObject;
import com.juzu.dz.message.BFMessage;
public class GoogleLogin {
private static volatile GoogleLogin sInstance;
private GoogleSignInClient mGoogleSignInClient;
private static final int REQUEST_CODE_GOOGLE_SIGN_IN = 1001; /* unique request id */
private static final String server_client_token = "22951947163-20850c0vsdknh7ts3nai4bs6j85dj5gl.apps.googleusercontent.com";
public static GoogleLogin getInstance()
{
if (sInstance == null) {
synchronized (GoogleLogin.class) {
if (sInstance == null) {
sInstance = new GoogleLogin();
}
}
}
return sInstance;
}
public void init(Activity activity){
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestId()
.requestIdToken(server_client_token)
.requestServerAuthCode(server_client_token)
.requestScopes(new Scope(Scopes.PLUS_ME))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(activity, gso);
}
public void login(Activity activity)
{
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
activity.startActivityForResult(signInIntent, REQUEST_CODE_GOOGLE_SIGN_IN);
}
public void logout(Activity activity)
{
mGoogleSignInClient.signOut().addOnCompleteListener(activity, new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGOUT_SUCCESS, "");
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_CODE_GOOGLE_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGIN_SUCCESS, createLoginInfo(account));
} catch (ApiException e) {
GooglePlugin.sendMessageToUnity(BFMessage.GOOGLE_LOGIN_FAILED, "google login failed e:" + e.getStatusCode() + " msg:" + e.getMessage());
}
}
private String createLoginInfo(GoogleSignInAccount account){
String idToken = account.getIdToken();
String uid = account.getId();
JSONObject result = new JSONObject();
try {
result.put("Token", idToken);
result.put("UserId", uid);
} catch (JSONException e) {
e.printStackTrace();
}
return result.toString();
}
}

View File

@ -1,299 +1,499 @@
package com.juzu.dz.third;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.analytics.FirebaseAnalytics;
// import com.google.firebase.crashlytics.FirebaseCrashlytics;
import com.juzu.dz.message.BFMessage;
import com.unity3d.player.UnityPlayer;
import java.util.Iterator;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
public class GooglePlugin {
private static final String LOG_TAG = "GooglePlugin";
private static GoogleLogin mGoogleLogin = null;
private static GoogleBilling mGoogleBilling = null;
// private static GoogleAdmobRewardedVideo mGoogleAdmobRewardedVideo = null;
private static Activity _activity;
public static FirebaseAnalytics mFirebaseAnalytics;
// private FirebaseCrashlytics mFirebaseCrashlytics;
public static void init(Activity activity){
_activity = activity;
mFirebaseAnalytics = FirebaseAnalytics.getInstance(_activity);
}
public static void initLogin()
{
if (mGoogleLogin == null)
{
mGoogleLogin = GoogleLogin.getInstance();
mGoogleLogin.init(_activity);
}
}
public static void initBilling()
{
if (mGoogleBilling == null)
{
mGoogleBilling = GoogleBilling.getInstance();
mGoogleBilling.init(_activity);
}
}
public static void initAdmobRewardedVideo()
{
Log.d("RewardedVideo", "android initAdmobRewardedVideo");
// if (mGoogleAdmobRewardedVideo == null)
// {
// mGoogleAdmobRewardedVideo = GoogleAdmobRewardedVideo.getInstance();
// mGoogleAdmobRewardedVideo.init(_activity);
// }
}
// 登录
public static void login()
{
if (mGoogleLogin != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleLogin.login(_activity);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_LOGIN_FAILED, "google login failed: not init");
}
}
// 登出
public static void logout()
{
if (mGoogleLogin != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleLogin.logout(_activity);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_LOGOUT_FAILED, "");
}
}
public static void pay(final String payType, final String productId, final String customMsg)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.pay(_activity, payType, productId, customMsg);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, "billing not init");
}
}
public static void queryProductsInfo(final String payType, final String productJson)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.queryProductsInfo(payType, productJson);
}
});
}else{
sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, "billing not init");
}
}
public static void consumeAsync(final String purchaseToken)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.consumeAsync(purchaseToken);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "billing not init");
}
}
public static void connectGoogleStore()
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.connectGoogleStore();
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, "billing not init");
}
}
public static void queryUncompleteOrder(final String payType)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.queryUncompleteOrder(payType);
}
});
}else{
sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
}
}
public static void querySubscribeOrder(final String payType)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.querySubscribeOrder(payType);
}
});
}else{
sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
}
}
public static void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (mGoogleLogin != null){
mGoogleLogin.onActivityResult(requestCode, resultCode, data);
}
}
public static void onDestroy()
{
if (mGoogleBilling != null){
mGoogleBilling.onDestroy();
}
}
public static void getFirebaseToken()
{
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w(LOG_TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
GooglePlugin.sendMessageToUnity(BFMessage.FIREBASE_TOKEN, token);
}
});
}
public static void tryLoadRewardedAd()
{
Log.w("", "tryLoadRewardedAd");
// if (mGoogleAdmobRewardedVideo != null)
// {
// mGoogleAdmobRewardedVideo.tryLoadRewardedAd(_activity);
// }
}
public static void showFullScreenAds()
{
Log.w("", "showFullScreenAds");
// if (mGoogleAdmobRewardedVideo != null)
// {
// mGoogleAdmobRewardedVideo.showFullScreenAds(_activity);
// }
}
// log event
public static void logEvent(String eventName, String data) throws JSONException {
Log.w("", "logEvent");
if (mFirebaseAnalytics == null) {
return;
}
JSONObject properties = new JSONObject(data);
Bundle bundle = new Bundle();
Iterator iter = properties.keys();
while (iter.hasNext()) {
String key = (String) iter.next();
Object value = properties.get(key);
setBundleValue(bundle, key, value);
}
mFirebaseAnalytics.logEvent(eventName, bundle);
}
public static void logEventBundle(String eventName, Bundle bundle){
Log.w("", "logEvent");
if (mFirebaseAnalytics == null) {
return;
}
mFirebaseAnalytics.logEvent(eventName, bundle);
}
// log crash
public static void logCrash(String key, String stack) {
// this.mFirebaseCrashlytics = FirebaseCrashlytics.getInstance();
// if (this.mFirebaseCrashlytics == null)
// return;
// this.mFirebaseCrashlytics.setCustomKey(key, stack);
}
// set bundle to type
private static void setBundleValue(Bundle bundle, String key, Object value) {
if (bundle == null)
return;
if (value instanceof Double)
bundle.putDouble(key, (Double) value);
else if (value instanceof Float)
bundle.putFloat(key, (Float)value);
else if (value instanceof Integer)
bundle.putInt(key, (Integer)value);
else if (value instanceof Long)
bundle.putLong(key, (Long) value);
else if (value instanceof Boolean)
bundle.putBoolean(key, (Boolean) value);
else
bundle.putString(key, (String) value);
}
public static void sendMessageToUnity(int code, String msg){
JSONObject data = new JSONObject();
try {
data.put("head", code);
data.put("body", msg);
} catch (JSONException e) {
e.printStackTrace();
}
Log.d(LOG_TAG, code + ":" + msg);
UnityPlayer.UnitySendMessage("SDKManager", "MsgFromAndroidOrIOS", data.toString());
}
public static void setAdPlacement(String placement){
// if (mGoogleAdmobRewardedVideo != null)
// {
// mGoogleAdmobRewardedVideo.setAdPlacement(placement);
// }
}
package com.juzu.dz.third;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.play.core.review.ReviewInfo;
import com.google.android.play.core.review.ReviewManager;
import com.google.android.play.core.review.ReviewManagerFactory;
import com.google.android.play.core.review.testing.FakeReviewManager;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.firebase.crashlytics.FirebaseCrashlytics;
import com.juzu.dz.message.BFMessage;
import com.unity3d.player.UnityPlayer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.json.JSONException;
import org.json.JSONObject;
import static com.google.firebase.crashlytics.internal.Logger.TAG;
import com.iabtcf.decoder.TCString;
import com.google.android.ump.ConsentDebugSettings;
import com.google.android.ump.ConsentForm.OnConsentFormDismissedListener;
import com.google.android.ump.ConsentInformation;
import com.google.android.ump.ConsentInformation.PrivacyOptionsRequirementStatus;
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.FormError;
import com.google.android.ump.UserMessagingPlatform;
public class GooglePlugin {
private static final String LOG_TAG = "GooglePlugin";
private static GoogleLogin mGoogleLogin = null;
private static GoogleBilling mGoogleBilling = null;
// private static GoogleAdmobRewardedVideo mGoogleAdmobRewardedVideo = null;
private static Activity _activity;
public static FirebaseAnalytics mFirebaseAnalytics;
// private FirebaseCrashlytics mFirebaseCrashlytics;
private static ConsentInformation consentInformation;
private final AtomicBoolean isMobileAdsInitializeCalled = new AtomicBoolean(false);
public static void init(Activity activity){
_activity = activity;
mFirebaseAnalytics = FirebaseAnalytics.getInstance(_activity);
}
public static void initLogin()
{
if (mGoogleLogin == null)
{
mGoogleLogin = GoogleLogin.getInstance();
mGoogleLogin.init(_activity);
}
}
public static void initBilling()
{
if (mGoogleBilling == null)
{
mGoogleBilling = GoogleBilling.getInstance();
mGoogleBilling.init(_activity);
}
}
public static void initAdmobRewardedVideo()
{
Log.d("RewardedVideo", "android initAdmobRewardedVideo");
// if (mGoogleAdmobRewardedVideo == null)
// {
// mGoogleAdmobRewardedVideo = GoogleAdmobRewardedVideo.getInstance();
// mGoogleAdmobRewardedVideo.init(_activity);
// }
}
public static void initGDPR()
{
initConsentInformation(_activity);
}
// 登录
public static void login()
{
if (mGoogleLogin != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleLogin.login(_activity);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_LOGIN_FAILED, "google login failed: not init");
}
}
// 登出
public static void logout()
{
if (mGoogleLogin != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleLogin.logout(_activity);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_LOGOUT_FAILED, "");
}
}
public static void pay(final String payType, final String productId, final String customMsg)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.pay(_activity, payType, productId, customMsg);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_PAY_FAILED, "billing not init");
}
}
public static void queryProductsInfo(final String payType, final String productJson)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.queryProductsInfo(payType, productJson);
}
});
}else{
sendMessageToUnity(BFMessage.QUERY_PRODUCT_FAILED, "billing not init");
}
}
public static void consumeAsync(final String purchaseToken)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.consumeAsync(purchaseToken);
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_CONSUME_FAILED, "billing not init");
}
}
public static void connectGoogleStore()
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.connectGoogleStore();
}
});
}else{
sendMessageToUnity(BFMessage.GOOGLE_CONNECT_FAILED, "billing not init");
}
}
public static void queryUncompleteOrder(final String payType)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.queryUncompleteOrder(payType);
}
});
}else{
sendMessageToUnity(BFMessage.QUERY_UNCOMPLETE_ORDER_FINISH, "");
}
}
public static void querySubscribeOrder(final String payType)
{
if (mGoogleBilling != null){
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mGoogleBilling.querySubscribeOrder(payType);
}
});
}else{
sendMessageToUnity(BFMessage.QUERY_SUBSCRIBE_FINISH, "");
}
}
public static void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (mGoogleLogin != null){
mGoogleLogin.onActivityResult(requestCode, resultCode, data);
}
}
public static void onDestroy()
{
if (mGoogleBilling != null){
mGoogleBilling.onDestroy();
}
}
public static void getFirebaseToken()
{
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
GooglePlugin.sendMessageToUnity(BFMessage.FIREBASE_TOKEN, token);
}
});
}
public static void tryLoadRewardedAd()
{
Log.w("", "tryLoadRewardedAd");
// if (mGoogleAdmobRewardedVideo != null)
// {
// mGoogleAdmobRewardedVideo.tryLoadRewardedAd(_activity);
// }
}
public static void showFullScreenAds()
{
Log.w("", "showFullScreenAds");
// if (mGoogleAdmobRewardedVideo != null)
// {
// mGoogleAdmobRewardedVideo.showFullScreenAds(_activity);
// }
}
// log event
public static void logEvent(String eventName, String data) throws JSONException {
Log.w("", "logEvent");
if (mFirebaseAnalytics == null) {
return;
}
JSONObject properties = new JSONObject(data);
Bundle bundle = new Bundle();
Iterator iter = properties.keys();
while (iter.hasNext()) {
String key = (String) iter.next();
Object value = properties.get(key);
setBundleValue(bundle, key, value);
}
mFirebaseAnalytics.logEvent(eventName, bundle);
}
public static void logEventBundle(String eventName, Bundle bundle){
Log.w("", "logEvent");
if (mFirebaseAnalytics == null) {
return;
}
mFirebaseAnalytics.logEvent(eventName, bundle);
}
// log crash
public static void logCrash(String key, String stack) {
// this.mFirebaseCrashlytics = FirebaseCrashlytics.getInstance();
// if (this.mFirebaseCrashlytics == null)
// return;
// this.mFirebaseCrashlytics.setCustomKey(key, stack);
}
// set bundle to type
private static void setBundleValue(Bundle bundle, String key, Object value) {
if (bundle == null)
return;
if (value instanceof Double)
bundle.putDouble(key, (Double) value);
else if (value instanceof Float)
bundle.putFloat(key, (Float)value);
else if (value instanceof Integer)
bundle.putInt(key, (Integer)value);
else if (value instanceof Long)
bundle.putLong(key, (Long) value);
else if (value instanceof Boolean)
bundle.putBoolean(key, (Boolean) value);
else
bundle.putString(key, (String) value);
}
public static void sendMessageToUnity(int code, String msg){
JSONObject data = new JSONObject();
try {
data.put("head", code);
data.put("body", msg);
} catch (JSONException e) {
e.printStackTrace();
}
Log.d(LOG_TAG, code + ":" + msg);
UnityPlayer.UnitySendMessage("SDKManager", "MsgFromAndroidOrIOS", data.toString());
}
public static void setAdPlacement(String placement){
// if (mGoogleAdmobRewardedVideo != null)
// {
// mGoogleAdmobRewardedVideo.setAdPlacement(placement);
// }
}
private static String getSign(String algorithm) {
try {
PackageInfo info = _activity.getPackageManager().getPackageInfo(
_activity.getPackageName(), PackageManager.GET_SIGNATURES);
byte[] cert = info.signatures[0].toByteArray();
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] publicKey = md.digest(cert);
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < publicKey.length; i++) {
String appendString = Integer.toHexString(0xFF & publicKey[i])
.toUpperCase(Locale.US);
if (appendString.length() == 1)
hexString.append("0");
hexString.append(appendString);
hexString.append(":");
}
String result = hexString.toString();
return result.substring(0, result.length() - 1);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
// 初始化GDPR
public static void initConsentInformation(Activity activity)
{
// ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(activity)
// .setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
// .addTestDeviceHashedId("F760B5027ECC69D34A80D3957A9841A9") // mumu:D77B7887E3BC1B47009579C304F39BE4 vivo:F760B5027ECC69D34A80D3957A9841A9
// .build();
// ConsentRequestParameters params = new ConsentRequestParameters
// .Builder()
// .setConsentDebugSettings(debugSettings)
// .build();
ConsentRequestParameters params = new ConsentRequestParameters
.Builder()
.setTagForUnderAgeOfConsent(false)
.build();
// Requesting an update to consent information should be called on every app launch.
consentInformation = UserMessagingPlatform.getConsentInformation(activity);
consentInformation.requestConsentInfoUpdate(
activity,
params,
() -> {
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
activity,
loadAndShowError -> {
if (loadAndShowError != null) {
// Consent gathering failed.
Log.w(TAG, String.format("%s: %s",
loadAndShowError.getErrorCode(),
loadAndShowError.getMessage()));
}
// Consent has been gathered.
GooglePlugin.monitorConsentString();
}
);
},
requestConsentError -> {
// Consent gathering failed.
Log.w(TAG, String.format("%s: %s",
requestConsentError.getErrorCode(),
requestConsentError.getMessage()));
});
// Check if you can initialize the Google Mobile Ads SDK in parallel
// while checking for new consent information. Consent obtained in
// the previous session can be used to request ads.
// 不管结果,直接初始化广告
// init(activity);
}
public static boolean isPrivacyOptionsRequired()
{
return consentInformation.getPrivacyOptionsRequirementStatus() == PrivacyOptionsRequirementStatus.REQUIRED;
}
public static void showPrivacyOptionsForm()
{
_activity.runOnUiThread(new Runnable() {
public void run() {
UserMessagingPlatform.showPrivacyOptionsForm(
_activity,
formError -> {
if (formError != null) {
// Handle the error.
}
}
);
}
});
}
public static void resetGDPR()
{
consentInformation.reset();
}
// GDPR IAB TCF
public static void monitorConsentString() {
if (mFirebaseAnalytics == null)
return;
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(UnityPlayer.currentActivity.getApplicationContext());
if (sharedPrefs == null)
return;
String iabKey = "IABTCF_TCString";
String tcString = sharedPrefs.getString(iabKey, "");
if (tcString == "" || tcString.isEmpty())
return;
// ad_storage
boolean adStorageAllowed = TCString.decode(tcString).getPurposesConsent().contains(1);
// Consent toggle in vendor setting (i.e. Google is not blocked from using consented data at vendor level)
boolean googleConsent = TCString.decode(tcString).getVendorConsent().contains(755);
// Legitimate interest toggle in vendor setting (i.e. Google is not blocked from their legitimate interest)
// boolean googleInterest = TCString.decode(tcString).getVendorLegitimateInterest().contains(755);
// We are checking if consent for ad_storage was given and that Google as vendor has not been excluded from using consented data
FirebaseAnalytics.ConsentStatus consentStatus = adStorageAllowed && googleConsent ? FirebaseAnalytics.ConsentStatus.GRANTED : FirebaseAnalytics.ConsentStatus.DENIED;
//
// Set consent types.
Map<FirebaseAnalytics.ConsentType, FirebaseAnalytics.ConsentStatus> consentMap = new EnumMap<>(FirebaseAnalytics.ConsentType.class);
consentMap.put(FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE, consentStatus);
consentMap.put(FirebaseAnalytics.ConsentType.AD_STORAGE, consentStatus);
consentMap.put(FirebaseAnalytics.ConsentType.AD_USER_DATA, consentStatus);
consentMap.put(FirebaseAnalytics.ConsentType.AD_PERSONALIZATION, consentStatus);
mFirebaseAnalytics.setConsent(consentMap);
}
public static void requestStoreReview()
{
Activity activity = UnityPlayer.currentActivity;
// 未实例Activity
if (activity == null)
{
return;
}
ReviewManager manager = ReviewManagerFactory.create(activity);
// ReviewManager manager = new FakeReviewManager(activity); // 使用FakeReviewManager进行测试
// 实例 Review Manager 失败
if (manager == null)
{
return;
}
Task<ReviewInfo> request = manager.requestReviewFlow();
// 实例Review Request失败
if (request == null)
{
return;
}
request.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
// We can get the ReviewInfo object
ReviewInfo reviewInfo = task.getResult();
// launch review
manager.launchReviewFlow(activity, reviewInfo);
}
});
}
}

View File

@ -1,136 +1,136 @@
/*
* Copyright (C) 2021 Google Inc. All rights reserved.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.juzu.dz.third;
/*
* This class is an sample of how you can check to make sure your purchases on the device came
* from Google Play. Putting code like this on your server will provide additional protection.
* <p>
* One thing that you may also wish to consider doing is caching purchase IDs to make replay
* attacks harder. The reason this code isn't just part of the library is to allow
* you to customize it (and rename it!) to make generic patching exploits more difficult.
*/
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
/**
* Security-related methods. For a secure implementation, all of this code should be implemented on
* a server that communicates with the application on the device.
*/
class Security {
static final private String TAG = "IABUtil/Security";
static final private String KEY_FACTORY_ALGORITHM = "RSA";
static final private String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* BASE_64_ENCODED_PUBLIC_KEY should be YOUR APPLICATION PUBLIC KEY. You currently get this
* from the Google Play developer console under the "Monetization Setup" category in the
* Licensing area. This build has been setup so that if you define base64EncodedPublicKey in
* your local.properties, it will be echoed into BuildConfig.
*/
/**
* Verifies that the data was signed with the given signature
*
* @param signedData the signed JSON string (signed, not encrypted)
* @param signature the signature for the data, signed with the private key
*/
static public boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if ((TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
|| TextUtils.isEmpty(signature))
) {
Log.w(TAG, "Purchase verification failed: missing data.");
return false;
}
try {
PublicKey key = generatePublicKey(base64PublicKey);
return verify(key, signedData, signature);
} catch (IOException e) {
Log.e(TAG, "Error generating PublicKey from encoded key: " + e.getMessage());
return false;
}
}
/**
* Generates a PublicKey instance from a string containing the Base64-encoded public key.
*
* @param encodedPublicKey Base64-encoded public key
* @throws IOException if encoding algorithm is not supported or key specification
* is invalid
*/
static private PublicKey generatePublicKey(String encodedPublicKey) throws IOException {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
String msg = "Invalid key specification: " + e;
Log.w(TAG, msg);
throw new IOException(msg);
}
}
/**
* Verifies that the signature from the server matches the computed signature on the data.
* Returns true if the data is correctly signed.
*
* @param publicKey public key associated with the developer account
* @param signedData signed data from server
* @param signature server signature
* @return true if the data and signature match
*/
static private Boolean verify(PublicKey publicKey, String signedData, String signature) {
byte[] signatureBytes;
try {
signatureBytes = Base64.decode(signature, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Base64 decoding failed.");
return false;
}
try {
Signature signatureAlgorithm = Signature.getInstance(SIGNATURE_ALGORITHM);
signatureAlgorithm.initVerify(publicKey);
signatureAlgorithm.update(signedData.getBytes());
if (!signatureAlgorithm.verify(signatureBytes)) {
Log.w(TAG, "Signature verification failed...");
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key specification.");
} catch (SignatureException e) {
Log.e(TAG, "Signature exception.");
}
return false;
}
}
/*
* Copyright (C) 2021 Google Inc. All rights reserved.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.juzu.dz.third;
/*
* This class is an sample of how you can check to make sure your purchases on the device came
* from Google Play. Putting code like this on your server will provide additional protection.
* <p>
* One thing that you may also wish to consider doing is caching purchase IDs to make replay
* attacks harder. The reason this code isn't just part of the library is to allow
* you to customize it (and rename it!) to make generic patching exploits more difficult.
*/
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
/**
* Security-related methods. For a secure implementation, all of this code should be implemented on
* a server that communicates with the application on the device.
*/
class Security {
static final private String TAG = "IABUtil/Security";
static final private String KEY_FACTORY_ALGORITHM = "RSA";
static final private String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* BASE_64_ENCODED_PUBLIC_KEY should be YOUR APPLICATION PUBLIC KEY. You currently get this
* from the Google Play developer console under the "Monetization Setup" category in the
* Licensing area. This build has been setup so that if you define base64EncodedPublicKey in
* your local.properties, it will be echoed into BuildConfig.
*/
/**
* Verifies that the data was signed with the given signature
*
* @param signedData the signed JSON string (signed, not encrypted)
* @param signature the signature for the data, signed with the private key
*/
static public boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if ((TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
|| TextUtils.isEmpty(signature))
) {
Log.w(TAG, "Purchase verification failed: missing data.");
return false;
}
try {
PublicKey key = generatePublicKey(base64PublicKey);
return verify(key, signedData, signature);
} catch (IOException e) {
Log.e(TAG, "Error generating PublicKey from encoded key: " + e.getMessage());
return false;
}
}
/**
* Generates a PublicKey instance from a string containing the Base64-encoded public key.
*
* @param encodedPublicKey Base64-encoded public key
* @throws IOException if encoding algorithm is not supported or key specification
* is invalid
*/
static private PublicKey generatePublicKey(String encodedPublicKey) throws IOException {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
String msg = "Invalid key specification: " + e;
Log.w(TAG, msg);
throw new IOException(msg);
}
}
/**
* Verifies that the signature from the server matches the computed signature on the data.
* Returns true if the data is correctly signed.
*
* @param publicKey public key associated with the developer account
* @param signedData signed data from server
* @param signature server signature
* @return true if the data and signature match
*/
static private Boolean verify(PublicKey publicKey, String signedData, String signature) {
byte[] signatureBytes;
try {
signatureBytes = Base64.decode(signature, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Base64 decoding failed.");
return false;
}
try {
Signature signatureAlgorithm = Signature.getInstance(SIGNATURE_ALGORITHM);
signatureAlgorithm.initVerify(publicKey);
signatureAlgorithm.update(signedData.getBytes());
if (!signatureAlgorithm.verify(signatureBytes)) {
Log.w(TAG, "Signature verification failed...");
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
// "RSA" is guaranteed to be available.
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key specification.");
} catch (SignatureException e) {
Log.e(TAG, "Signature exception.");
}
return false;
}
}

View File

@ -0,0 +1,187 @@
package com.unity.androidnotifications;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_ID;
import static com.unity.androidnotifications.UnityNotificationManager.TAG_UNITY;
import android.app.Notification;
import android.util.Log;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedTransferQueue;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class UnityNotificationBackgroundThread extends Thread {
private static abstract class Task {
// returns true if notificationIds was modified (needs to be saved)
public abstract boolean run(UnityNotificationManager manager, ConcurrentHashMap<Integer, Notification.Builder> notifications);
}
private static class ScheduleNotificationTask extends Task {
private int notificationId;
private Notification.Builder notificationBuilder;
private boolean isCustomized;
private boolean isNew;
public ScheduleNotificationTask(int id, Notification.Builder builder, boolean customized, boolean addedNew) {
notificationId = id;
notificationBuilder = builder;
isCustomized = customized;
isNew = addedNew;
}
@Override
public boolean run(UnityNotificationManager manager, ConcurrentHashMap<Integer, Notification.Builder> notifications) {
String id = String.valueOf(notificationId);
Integer ID = Integer.valueOf(notificationId);
boolean didSchedule = false;
try {
UnityNotificationManager.mUnityNotificationManager.performNotificationScheduling(notificationId, notificationBuilder, isCustomized);
didSchedule = true;
} finally {
// if failed to schedule or replace, remove
if (!didSchedule) {
notifications.remove(notificationId);
manager.cancelPendingNotificationIntent(notificationId);
manager.deleteExpiredNotificationIntent(id);
}
}
return isNew;
}
}
private static class CancelNotificationTask extends Task {
private int notificationId;
public CancelNotificationTask(int id) {
notificationId = id;
}
@Override
public boolean run(UnityNotificationManager manager, ConcurrentHashMap<Integer, Notification.Builder> notifications) {
manager.cancelPendingNotificationIntent(notificationId);
if (notifications.remove(notificationId) != null) {
manager.deleteExpiredNotificationIntent(String.valueOf(notificationId));
return true;
}
return false;
}
}
private static class CancelAllNotificationsTask extends Task {
@Override
public boolean run(UnityNotificationManager manager, ConcurrentHashMap<Integer, Notification.Builder> notifications) {
if (notifications.isEmpty())
return false;
Enumeration<Integer> ids = notifications.keys();
while (ids.hasMoreElements()) {
Integer notificationId = ids.nextElement();
manager.cancelPendingNotificationIntent(notificationId);
manager.deleteExpiredNotificationIntent(String.valueOf(notificationId));
}
notifications.clear();
return true;
}
}
private static class HousekeepingTask extends Task {
UnityNotificationBackgroundThread thread;
public HousekeepingTask(UnityNotificationBackgroundThread th) {
thread = th;
}
@Override
public boolean run(UnityNotificationManager manager, ConcurrentHashMap<Integer, Notification.Builder> notifications) {
HashSet<String> notificationIds = new HashSet<>();
Enumeration<Integer> ids = notifications.keys();
while (ids.hasMoreElements()) {
notificationIds.add(String.valueOf(ids.nextElement()));
}
thread.performHousekeeping(notificationIds);
return false;
}
}
private static final int TASKS_FOR_HOUSEKEEPING = 50;
private LinkedTransferQueue<Task> mTasks = new LinkedTransferQueue();
private ConcurrentHashMap<Integer, Notification.Builder> mScheduledNotifications;
private UnityNotificationManager mManager;
private int mTasksSinceHousekeeping = TASKS_FOR_HOUSEKEEPING; // we want hoursekeeping at the start
public UnityNotificationBackgroundThread(UnityNotificationManager manager, ConcurrentHashMap<Integer, Notification.Builder> scheduledNotifications) {
mManager = manager;
mScheduledNotifications = scheduledNotifications;
// rescheduling after reboot may have loaded, otherwise load here
if (mScheduledNotifications.size() == 0)
loadNotifications();
}
public void enqueueNotification(int id, Notification.Builder notificationBuilder, boolean customized, boolean addedNew) {
mTasks.add(new UnityNotificationBackgroundThread.ScheduleNotificationTask(id, notificationBuilder, customized, addedNew));
}
public void enqueueCancelNotification(int id) {
mTasks.add(new CancelNotificationTask(id));
}
public void enqueueCancelAllNotifications() {
mTasks.add(new CancelAllNotificationsTask());
}
private void enqueueHousekeeping() {
mTasks.add(new HousekeepingTask(this));
}
@Override
public void run() {
boolean haveChanges = false;
while (true) {
try {
Task task = mTasks.take();
haveChanges |= executeTask(mManager, task, mScheduledNotifications);
if (!(task instanceof HousekeepingTask))
++mTasksSinceHousekeeping;
if (mTasks.size() == 0 && haveChanges) {
haveChanges = false;
enqueueHousekeeping();
}
} catch (InterruptedException e) {
if (mTasks.isEmpty())
break;
}
}
}
private boolean executeTask(UnityNotificationManager manager, Task task, ConcurrentHashMap<Integer, Notification.Builder> notifications) {
try {
return task.run(manager, notifications);
} catch (Exception e) {
Log.e(TAG_UNITY, "Exception executing notification task", e);
return false;
}
}
private void performHousekeeping(Set<String> notificationIds) {
// don't do housekeeping if last task we did was housekeeping (other=1)
boolean performHousekeeping = mTasksSinceHousekeeping >= TASKS_FOR_HOUSEKEEPING;
mTasksSinceHousekeeping = 0;
if (performHousekeeping)
mManager.performNotificationHousekeeping(notificationIds);
mManager.saveScheduledNotificationIDs(notificationIds);
}
private void loadNotifications() {
List<Notification.Builder> notifications = mManager.loadSavedNotifications();
for (Notification.Builder builder : notifications) {
int id = builder.getExtras().getInt(KEY_ID, -1);
mScheduledNotifications.put(id, builder);
}
}
}

View File

@ -0,0 +1,67 @@
package com.unity.androidnotifications;
import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_FIRE_TIME;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_ID;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_REPEAT_INTERVAL;
import static com.unity.androidnotifications.UnityNotificationManager.TAG_UNITY;
public class UnityNotificationRestartOnBootReceiver extends BroadcastReceiver {
private static final long EXPIRATION_TRESHOLD = 600000; // 10 minutes
@Override
public void onReceive(Context context, Intent received_intent) {
Log.d(TAG_UNITY, "Rescheduling notifications after restart");
if (Intent.ACTION_BOOT_COMPLETED.equals(received_intent.getAction())) {
AsyncTask.execute(() -> { rescheduleSavedNotifications(context); });
}
}
private static void rescheduleSavedNotifications(Context context) {
UnityNotificationManager manager = UnityNotificationManager.getNotificationManagerImpl(context);
List<Notification.Builder> saved_notifications = manager.loadSavedNotifications();
Date currentDate = Calendar.getInstance().getTime();
for (Notification.Builder notificationBuilder : saved_notifications) {
rescheduleNotification(manager, currentDate, notificationBuilder);
}
}
private static boolean rescheduleNotification(UnityNotificationManager manager, Date currentDate, Notification.Builder notificationBuilder) {
try {
Bundle extras = notificationBuilder.getExtras();
long repeatInterval = extras.getLong(KEY_REPEAT_INTERVAL, 0L);
long fireTime = extras.getLong(KEY_FIRE_TIME, 0L);
Date fireTimeDate = new Date(fireTime);
boolean isRepeatable = repeatInterval > 0;
if (fireTimeDate.after(currentDate) || isRepeatable) {
manager.scheduleAlarmWithNotification(notificationBuilder);
return true;
} else if (currentDate.getTime() - fireTime < EXPIRATION_TRESHOLD) {
// notification is in the past, but not by much, send now
int id = extras.getInt(KEY_ID);
manager.notify(id, notificationBuilder);
return true;
} else {
Log.d(TAG_UNITY, "Notification expired, not rescheduling, ID: " + extras.getInt(KEY_ID, -1));
return false;
}
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to reschedule notification", e);
return false;
}
}
}

View File

@ -0,0 +1,654 @@
package com.unity.androidnotifications;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Base64;
import android.util.Log;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_CHANNEL_ID;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_FIRE_TIME;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_ID;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_INTENT_DATA;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_LARGE_ICON;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_NOTIFICATION;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_REPEAT_INTERVAL;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_SMALL_ICON;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_SHOW_IN_FOREGROUND;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_BIG_LARGE_ICON;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_BIG_PICTURE;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_BIG_CONTENT_TITLE;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_BIG_SUMMARY_TEXT;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_BIG_CONTENT_DESCRIPTION;
import static com.unity.androidnotifications.UnityNotificationManager.KEY_BIG_SHOW_WHEN_COLLAPSED;
import static com.unity.androidnotifications.UnityNotificationManager.TAG_UNITY;
class UnityNotificationUtilities {
/*
We serialize notifications and save them to shared prefs, so that if app is killed, we can recreate them.
The serialized BLOB starts with a four byte magic number descibing serialization type, followed by an integer version.
IMPORTANT: IF YOU DO A CHANGE THAT AFFECTS THE LAYOUT, BUMP THE VERSION, AND ENSURE OLD VERSION STILL DESERIALIZES. ADD TEST.
In real life app can get updated having old serialized notifications present, so we should be able to deserialize them.
*/
// magic stands for "Unity Mobile Notifications Notification"
static final byte[] UNITY_MAGIC_NUMBER = new byte[] { 'U', 'M', 'N', 'N'};
private static final byte[] UNITY_MAGIC_NUMBER_PARCELLED = new byte[] { 'U', 'M', 'N', 'P'};
private static final int NOTIFICATION_SERIALIZATION_VERSION = 3;
private static final int INTENT_SERIALIZATION_VERSION = 0;
static final String SAVED_NOTIFICATION_PRIMARY_KEY = "data";
static final String SAVED_NOTIFICATION_FALLBACK_KEY = "fallback.data";
protected static int findResourceIdInContextByName(Context context, String name) {
if (name == null)
return 0;
try {
Resources res = context.getResources();
if (res != null) {
int id = res.getIdentifier(name, "mipmap", context.getPackageName());
if (id == 0)
return res.getIdentifier(name, "drawable", context.getPackageName());
else
return id;
}
return 0;
} catch (Resources.NotFoundException e) {
return 0;
}
}
/* Originally we used to serialize a bundle with predefined list of values.
After we exposed entire Notification.Builder to users, this is not sufficient anymore.
Unfortunately, while Notification itself is Parcelable and can be marshalled to bytes,
it's contents are not guaranteed to be (Binder objects).
Hence what we try to do here is:
- serialize as is if notification is possibly customized by user
- otherwise serialize our stuff, since there is nothing more
*/
protected static void serializeNotification(SharedPreferences prefs, Notification notification, boolean serializeParcel) {
try {
String serialized;
ByteArrayOutputStream data = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(data);
if (serializeParcel) {
Intent intent = new Intent();
intent.putExtra(KEY_NOTIFICATION, notification);
if (serializeNotificationParcel(intent, out)) {
out.close();
byte[] bytes = data.toByteArray();
serialized = Base64.encodeToString(bytes, 0, bytes.length, 0);
} else {
return; // failed
}
}
else {
if (serializeNotificationCustom(notification, out)) {
out.flush();
byte[] bytes = data.toByteArray();
serialized = Base64.encodeToString(bytes, 0, bytes.length, 0);
} else {
return; // failed
}
}
SharedPreferences.Editor editor = prefs.edit().clear();
editor.putString(SAVED_NOTIFICATION_PRIMARY_KEY, serialized);
editor.apply();
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to serialize notification", e);
}
}
static boolean serializeNotificationParcel(Intent intent, DataOutputStream out) {
try {
byte[] bytes = serializeParcelable(intent);
if (bytes == null || bytes.length == 0)
return false;
out.write(UNITY_MAGIC_NUMBER_PARCELLED);
out.writeInt(INTENT_SERIALIZATION_VERSION);
out.writeInt(bytes.length);
out.write(bytes);
return true;
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to serialize notification as Parcel", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to serialize notification as Parcel", e);
}
return false;
}
private static boolean serializeNotificationCustom(Notification notification, DataOutputStream out) {
try {
out.write(UNITY_MAGIC_NUMBER);
out.writeInt(NOTIFICATION_SERIALIZATION_VERSION);
// serialize extras
boolean showWhen = notification.extras.getBoolean(Notification.EXTRA_SHOW_WHEN, false);
out.writeInt(notification.extras.getInt(KEY_ID));
serializeString(out, notification.extras.getString(Notification.EXTRA_TITLE));
serializeString(out, notification.extras.getString(Notification.EXTRA_TEXT));
serializeString(out, notification.extras.getString(KEY_SMALL_ICON));
serializeString(out, notification.extras.getString(KEY_LARGE_ICON));
out.writeLong(notification.extras.getLong(KEY_FIRE_TIME, -1));
out.writeLong(notification.extras.getLong(KEY_REPEAT_INTERVAL, -1));
serializeString(out, Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? null : notification.extras.getString(Notification.EXTRA_BIG_TEXT));
out.writeBoolean(notification.extras.getBoolean(Notification.EXTRA_SHOW_CHRONOMETER, false));
out.writeBoolean(showWhen);
serializeString(out, notification.extras.getString(KEY_INTENT_DATA));
out.writeBoolean(notification.extras.getBoolean(KEY_SHOW_IN_FOREGROUND, true));
String bigPicture = notification.extras.getString(KEY_BIG_PICTURE);
serializeString(out, bigPicture);
if (bigPicture != null && bigPicture.length() > 0) {
// the following only need to be put in if big picture is there
serializeString(out, notification.extras.getString(KEY_BIG_LARGE_ICON));
serializeString(out, notification.extras.getString(KEY_BIG_CONTENT_TITLE));
serializeString(out, notification.extras.getString(KEY_BIG_CONTENT_DESCRIPTION));
serializeString(out, notification.extras.getString(KEY_BIG_SUMMARY_TEXT));
out.writeBoolean(notification.extras.getBoolean(KEY_BIG_SHOW_WHEN_COLLAPSED, false));
}
serializeString(out, Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? null : notification.getChannelId());
Integer color = UnityNotificationManager.getNotificationColor(notification);
out.writeBoolean(color != null);
if (color != null)
out.writeInt(color);
out.writeInt(notification.number);
out.writeBoolean(0 != (notification.flags & Notification.FLAG_AUTO_CANCEL));
serializeString(out, notification.getGroup());
out.writeBoolean(0 != (notification.flags & Notification.FLAG_GROUP_SUMMARY));
out.writeInt(UnityNotificationManager.getNotificationGroupAlertBehavior(notification));
serializeString(out, notification.getSortKey());
if (showWhen)
out.writeLong(notification.when);
return true;
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to serialize notification", e);
return false;
}
}
static void serializeString(DataOutputStream out, String s) throws IOException {
if (s == null || s.length() == 0)
out.writeInt(0);
else {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
out.writeInt(bytes.length);
out.write(bytes);
}
}
static byte[] serializeParcelable(Parcelable obj) {
try {
Parcel p = Parcel.obtain();
Bundle b = new Bundle();
b.putParcelable("obj", obj);
p.writeParcelable(b, 0);
byte[] result = p.marshall();
p.recycle();
return result;
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to serialize Parcelable", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to serialize Parcelable", e);
}
return null;
}
protected static Object deserializeNotification(Context context, SharedPreferences prefs) {
String serializedIntentData = prefs.getString(SAVED_NOTIFICATION_PRIMARY_KEY, "");
if (null == serializedIntentData || serializedIntentData.length() <= 0)
return null;
byte[] bytes = Base64.decode(serializedIntentData, 0);
Object notification = deserializeNotification(context, bytes);
if (notification != null)
return notification;
serializedIntentData = prefs.getString(SAVED_NOTIFICATION_FALLBACK_KEY, "");
if (null == serializedIntentData || serializedIntentData.length() <= 0)
return null;
bytes = Base64.decode(serializedIntentData, 0);
return deserializeNotification(context, bytes);
}
/* See serialization method above for explaination of fallbacks.
This one matches it with one additional fallback: support for "old" bundle serialization.
*/
private static Object deserializeNotification(Context context, byte[] bytes) {
ByteArrayInputStream data = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(data);
Notification notification = deserializeNotificationParcelable(in);
if (notification != null)
return notification;
data.reset();
Notification.Builder builder = deserializeNotificationCustom(context, in);
if (builder == null) {
builder = deserializedFromOldIntent(context, bytes);
}
return builder;
}
private static boolean readAndCheckMagicNumber(DataInputStream in, byte[] magic) {
try {
boolean magicNumberMatch = true;
for (int i = 0; i < magic.length; ++i) {
byte b = in.readByte();
if (b != magic[i]) {
magicNumberMatch = false;
break;
}
}
return magicNumberMatch;
} catch (Exception e) {
return false;
}
}
private static Notification deserializeNotificationParcelable(DataInputStream in) {
try {
if (!readAndCheckMagicNumber(in, UNITY_MAGIC_NUMBER_PARCELLED))
return null;
int version = in.readInt();
if (version < 0 || version > INTENT_SERIALIZATION_VERSION)
return null;
Intent intent = deserializeParcelable(in);
Notification notification = intent.getParcelableExtra(KEY_NOTIFICATION);
return notification;
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to deserialize notification intent", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to deserialize notification intent", e);
}
return null;
}
private static Notification.Builder deserializeNotificationCustom(Context context, DataInputStream in) {
try {
if (!readAndCheckMagicNumber(in, UNITY_MAGIC_NUMBER))
return null;
int version = in.readInt();
if (version < 0 || version > NOTIFICATION_SERIALIZATION_VERSION)
return null;
// deserialize extras
int id = 0;
String title, text, smallIcon, largeIcon, bigText, intentData;
long fireTime, repeatInterval;
boolean usesStopWatch, showWhen, showInForeground = true;
Bundle extras = null;
String bigPicture = null, bigLargeIcon = null, bigContentTitle = null, bigSummary = null, bigContentDesc = null;
boolean bigShowWhenCollapsed = false;
if (version < 2) {
// no longer serialized since v2
extras = deserializeParcelable(in);
}
// before v2 it was extras or variables, since 2 always variables
if (extras == null) {
// extras serialized manually
id = in.readInt();
title = deserializeString(in);
text = deserializeString(in);
smallIcon = deserializeString(in);
largeIcon = deserializeString(in);
fireTime = in.readLong();
repeatInterval = in.readLong();
bigText = deserializeString(in);
usesStopWatch = in.readBoolean();
showWhen = in.readBoolean();
intentData = deserializeString(in);
if (version > 0)
showInForeground = in.readBoolean();
if (version >= 3) {
bigPicture = deserializeString(in);
if (bigPicture != null && bigPicture.length() > 0) {
// the following only need to be put in if big picture is there
bigLargeIcon = deserializeString(in);
bigContentTitle = deserializeString(in);
bigContentDesc = deserializeString(in);
bigSummary = deserializeString(in);
bigShowWhenCollapsed = in.readBoolean();
}
}
} else {
title = extras.getString(Notification.EXTRA_TITLE);
text = extras.getString(Notification.EXTRA_TEXT);
smallIcon = extras.getString(KEY_SMALL_ICON);
largeIcon = extras.getString(KEY_LARGE_ICON);
fireTime = extras.getLong(KEY_FIRE_TIME, -1);
repeatInterval = extras.getLong(KEY_REPEAT_INTERVAL, -1);
bigText = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? null : extras.getString(Notification.EXTRA_BIG_TEXT);
usesStopWatch = extras.getBoolean(Notification.EXTRA_SHOW_CHRONOMETER, false);
showWhen = extras.getBoolean(Notification.EXTRA_SHOW_WHEN, false);
intentData = extras.getString(KEY_INTENT_DATA);
}
String channelId = deserializeString(in);
boolean haveColor = in.readBoolean();
int color = 0;
if (haveColor)
color = in.readInt();
int number = in.readInt();
boolean shouldAutoCancel = in.readBoolean();
String group = deserializeString(in);
boolean groupSummary = in.readBoolean();
int groupAlertBehavior = in.readInt();
String sortKey = deserializeString(in);
long when = showWhen ? in.readLong() : 0;
UnityNotificationManager manager = UnityNotificationManager.getNotificationManagerImpl(context);
Notification.Builder builder = manager.createNotificationBuilder(channelId);
if (extras != null)
builder.setExtras(extras);
else {
builder.getExtras().putInt(KEY_ID, id);
UnityNotificationManager.setNotificationIcon(builder, KEY_SMALL_ICON, smallIcon);
UnityNotificationManager.setNotificationIcon(builder, KEY_LARGE_ICON, largeIcon);
if (fireTime != -1)
builder.getExtras().putLong(KEY_FIRE_TIME, fireTime);
if (repeatInterval != -1)
builder.getExtras().putLong(KEY_REPEAT_INTERVAL, repeatInterval);
if (intentData != null)
builder.getExtras().putString(KEY_INTENT_DATA, intentData);
builder.getExtras().putBoolean(KEY_SHOW_IN_FOREGROUND, showInForeground);
}
if (title != null)
builder.setContentTitle(title);
if (text != null)
builder.setContentText(text);
if (bigText != null)
builder.setStyle(new Notification.BigTextStyle().bigText(bigText));
else if (bigPicture != null)
manager.setupBigPictureStyle(builder, bigLargeIcon, bigPicture, bigContentTitle, bigContentDesc, bigSummary, bigShowWhenCollapsed);
if (haveColor)
UnityNotificationManager.setNotificationColor(builder, color);
if (number >= 0)
builder.setNumber(number);
builder.setAutoCancel(shouldAutoCancel);
UnityNotificationManager.setNotificationUsesChronometer(builder, usesStopWatch);
if (group != null && group.length() > 0)
builder.setGroup(group);
builder.setGroupSummary(groupSummary);
UnityNotificationManager.setNotificationGroupAlertBehavior(builder, groupAlertBehavior);
if (sortKey != null && sortKey.length() > 0)
builder.setSortKey(sortKey);
if (showWhen) {
builder.setShowWhen(true);
builder.setWhen(when);
}
return builder;
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to deserialize notification", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to deserialize notification", e);
}
return null;
}
private static Notification.Builder deserializedFromOldIntent(Context context, byte[] bytes) {
try {
Parcel p = Parcel.obtain();
p.unmarshall(bytes, 0, bytes.length);
p.setDataPosition(0);
Bundle bundle = new Bundle();
bundle.readFromParcel(p);
int id = bundle.getInt(KEY_ID, -1);
String channelId = bundle.getString("channelID");
String textTitle = bundle.getString("textTitle");
String textContent = bundle.getString("textContent");
String smallIcon = bundle.getString("smallIconStr");
boolean autoCancel = bundle.getBoolean("autoCancel", false);
boolean usesChronometer = bundle.getBoolean("usesChronometer", false);
long fireTime = bundle.getLong(KEY_FIRE_TIME, -1);
long repeatInterval = bundle.getLong(KEY_REPEAT_INTERVAL, -1);
String largeIcon = bundle.getString("largeIconStr");
int style = bundle.getInt("style", -1);
int color = bundle.getInt("color", 0);
int number = bundle.getInt("number", 0);
String intentData = bundle.getString(KEY_INTENT_DATA);
String group = bundle.getString("group");
boolean groupSummary = bundle.getBoolean("groupSummary", false);
String sortKey = bundle.getString("sortKey");
int groupAlertBehaviour = bundle.getInt("groupAlertBehaviour", -1);
boolean showTimestamp = bundle.getBoolean("showTimestamp", false);
Notification.Builder builder = UnityNotificationManager.getNotificationManagerImpl(context).createNotificationBuilder(channelId);
builder.getExtras().putInt(KEY_ID, id);
builder.setContentTitle(textTitle);
builder.setContentText(textContent);
UnityNotificationManager.setNotificationIcon(builder, KEY_SMALL_ICON, smallIcon);
builder.setAutoCancel(autoCancel);
builder.setUsesChronometer(usesChronometer);
builder.getExtras().putLong(KEY_FIRE_TIME, fireTime);
builder.getExtras().putLong(KEY_REPEAT_INTERVAL, repeatInterval);
UnityNotificationManager.setNotificationIcon(builder, KEY_LARGE_ICON, largeIcon);
if (style == 2)
builder.setStyle(new Notification.BigTextStyle().bigText(textContent));
if (color != 0)
UnityNotificationManager.setNotificationColor(builder, color);
if (number >= 0)
builder.setNumber(number);
if (intentData != null)
builder.getExtras().putString(KEY_INTENT_DATA, intentData);
if (null != group && group.length() > 0)
builder.setGroup(group);
builder.setGroupSummary(groupSummary);
if (null != sortKey && sortKey.length() > 0)
builder.setSortKey(sortKey);
UnityNotificationManager.setNotificationGroupAlertBehavior(builder, groupAlertBehaviour);
builder.setShowWhen(showTimestamp);
return builder;
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to deserialize old style notification", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to deserialize old style notification", e);
}
return null;
}
private static String deserializeString(DataInputStream in) throws IOException {
int length = in.readInt();
if (length <= 0)
return null;
byte[] bytes = new byte[length];
int didRead = in.read(bytes);
if (didRead != bytes.length)
throw new IOException("Insufficient amount of bytes read");
return new String(bytes, StandardCharsets.UTF_8);
}
private static <T extends Parcelable> T deserializeParcelable(DataInputStream in) throws IOException {
int length = in.readInt();
if (length <= 0)
return null;
byte[] bytes = new byte[length];
int didRead = in.read(bytes);
if (didRead != bytes.length)
throw new IOException("Insufficient amount of bytes read");
try {
Parcel p = Parcel.obtain();
p.unmarshall(bytes, 0, bytes.length);
p.setDataPosition(0);
Bundle b = p.readParcelable(UnityNotificationUtilities.class.getClassLoader());
p.recycle();
if (b != null) {
return b.getParcelable("obj");
}
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to deserialize parcelable", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to deserialize parcelable", e);
}
return null;
}
// Returns Activity class to be opened when notification is tapped
// Search is done in this order:
// * class specified in meta-data key custom_notification_android_activity
// * the only enabled activity with name ending in either .UnityPlayerActivity or .UnityPlayerGameActivity
// * the only enabled activity in the package
protected static Class<?> getOpenAppActivity(Context context) {
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
if (bundle.containsKey("custom_notification_android_activity")) {
try {
return Class.forName(bundle.getString("custom_notification_android_activity"));
} catch (ClassNotFoundException e) {
Log.e(TAG_UNITY, "Specified activity class for notifications not found: " + e.getMessage());
}
}
Log.w(TAG_UNITY, "No custom_notification_android_activity found, attempting to find app activity class");
ActivityInfo[] aInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES).activities;
if (aInfo == null) {
Log.e(TAG_UNITY, "Could not get package activities");
return null;
}
String activityClassName = null;
boolean activityIsUnity = false, activityConflict = false;
for (ActivityInfo info : aInfo) {
// activity alias not supported
if (!info.enabled || info.targetActivity != null)
continue;
boolean candidateIsUnity = isUnityActivity(info.name);
if (activityClassName == null) {
activityClassName = info.name;
activityIsUnity = candidateIsUnity;
continue;
}
// two Unity activities is a hard conflict
// two non-Unity activities is a conflict unless we find a Unity activity later on
if (activityIsUnity == candidateIsUnity) {
activityConflict = true;
if (activityIsUnity && candidateIsUnity)
break;
continue;
}
if (candidateIsUnity) {
activityClassName = info.name;
activityIsUnity = candidateIsUnity;
activityConflict = false;
}
}
if (activityConflict) {
Log.e(TAG_UNITY, "Multiple choices for activity for notifications, set activity explicitly in Notification Settings");
return null;
}
if (activityClassName == null) {
Log.e(TAG_UNITY, "Activity class for notifications not found");
return null;
}
return Class.forName(activityClassName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
Log.e(TAG_UNITY, "Failed to find activity class: " + e.getMessage());
}
return null;
}
private static boolean isUnityActivity(String name) {
return name.endsWith(".UnityPlayerActivity") || name.endsWith(".UnityPlayerGameActivity");
}
protected static Notification.Builder recoverBuilder(Context context, Notification notification) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Notification.Builder builder = Notification.Builder.recoverBuilder(context, notification);
// extras not recovered, transfer manually
builder.setExtras(notification.extras);
return builder;
}
} catch (Exception e) {
Log.e(TAG_UNITY, "Failed to recover builder for notification!", e);
} catch (OutOfMemoryError e) {
Log.e(TAG_UNITY, "Failed to recover builder for notification!", e);
}
return recoverBuilderCustom(context, notification);
}
private static Notification.Builder recoverBuilderCustom(Context context, Notification notification) {
String channelID = notification.extras.getString(KEY_CHANNEL_ID);
Notification.Builder builder = UnityNotificationManager.getNotificationManagerImpl(context).createNotificationBuilder(channelID);
UnityNotificationManager.setNotificationIcon(builder, KEY_SMALL_ICON, notification.extras.getString(KEY_SMALL_ICON));
String largeIcon = notification.extras.getString(KEY_LARGE_ICON);
if (largeIcon != null && !largeIcon.isEmpty())
UnityNotificationManager.setNotificationIcon(builder, KEY_LARGE_ICON, largeIcon);
builder.setContentTitle(notification.extras.getString(Notification.EXTRA_TITLE));
builder.setContentText(notification.extras.getString(Notification.EXTRA_TEXT));
builder.setAutoCancel(0 != (notification.flags & Notification.FLAG_AUTO_CANCEL));
if (notification.number >= 0)
builder.setNumber(notification.number);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String bigText = notification.extras.getString(Notification.EXTRA_BIG_TEXT);
if (bigText != null)
builder.setStyle(new Notification.BigTextStyle().bigText(bigText));
}
builder.setWhen(notification.when);
String group = notification.getGroup();
if (group != null && !group.isEmpty())
builder.setGroup(group);
builder.setGroupSummary(0 != (notification.flags & Notification.FLAG_GROUP_SUMMARY));
String sortKey = notification.getSortKey();
if (sortKey != null && !sortKey.isEmpty())
builder.setSortKey(sortKey);
builder.setShowWhen(notification.extras.getBoolean(Notification.EXTRA_SHOW_WHEN, false));
Integer color = UnityNotificationManager.getNotificationColor(notification);
if (color != null)
UnityNotificationManager.setNotificationColor(builder, color);
UnityNotificationManager.setNotificationUsesChronometer(builder, notification.extras.getBoolean(Notification.EXTRA_SHOW_CHRONOMETER, false));
UnityNotificationManager.setNotificationGroupAlertBehavior(builder, UnityNotificationManager.getNotificationGroupAlertBehavior(notification));
builder.getExtras().putInt(KEY_ID, notification.extras.getInt(KEY_ID, 0));
builder.getExtras().putLong(KEY_REPEAT_INTERVAL, notification.extras.getLong(KEY_REPEAT_INTERVAL, 0));
builder.getExtras().putLong(KEY_FIRE_TIME, notification.extras.getLong(KEY_FIRE_TIME, 0));
String intentData = notification.extras.getString(KEY_INTENT_DATA);
if (intentData != null && !intentData.isEmpty())
builder.getExtras().putString(KEY_INTENT_DATA, intentData);
return builder;
}
}

Binary file not shown.

View File

@ -0,0 +1 @@
juzu_dz0!