summaryrefslogtreecommitdiff
path: root/platform/android/java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/java')
-rw-r--r--platform/android/java/app/AndroidManifest.xml5
-rw-r--r--platform/android/java/app/build.gradle74
-rw-r--r--platform/android/java/app/config.gradle101
-rw-r--r--platform/android/java/app/res/drawable/splash.pngbin0 -> 14766 bytes
-rw-r--r--platform/android/java/app/res/drawable/splash_bg_color.pngbin0 -> 1360 bytes
-rw-r--r--platform/android/java/app/res/drawable/splash_drawable.xml12
-rw-r--r--platform/android/java/app/res/values-ar/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-ar/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-bg/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-bg/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-ca/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-ca/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-cs/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-cs/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-da/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-da/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-de/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-de/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-el/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-el/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-en/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-en/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-es-rES/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-es-rES/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-es/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-es/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-fa/godot_project_name_string.xml5
-rw-r--r--platform/android/java/app/res/values-fi/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-fi/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-fr/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-fr/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-hi/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-hi/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-hr/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-hr/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-hu/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-hu/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-in/godot_project_name_string.xml5
-rw-r--r--platform/android/java/app/res/values-it/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-it/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-iw/godot_project_name_string.xml5
-rw-r--r--platform/android/java/app/res/values-ja/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-ja/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-ko/godot_project_name_string.xml5
-rw-r--r--platform/android/java/app/res/values-lt/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-lt/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-lv/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-lv/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-nb/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-nb/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-nl/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-nl/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-pl/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-pl/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-pt/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-pt/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-ro/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-ro/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-ru/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-ru/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-sk/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-sk/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-sl/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-sl/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-sr/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-sr/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-sv/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-sv/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-th/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-th/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-tl/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-tl/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-tr/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-tr/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-uk/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-uk/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-vi/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-vi/strings.xml)3
-rw-r--r--platform/android/java/app/res/values-zh-rHK/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-zh-rHK/strings.xml)1
-rw-r--r--platform/android/java/app/res/values-zh-rTW/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-zh-rTW/strings.xml)1
-rw-r--r--platform/android/java/app/res/values-zh/godot_project_name_string.xml (renamed from platform/android/java/lib/res/values-zh-rCN/strings.xml)1
-rw-r--r--platform/android/java/app/res/values/godot_project_name_string.xml5
-rw-r--r--platform/android/java/app/res/values/themes.xml10
-rw-r--r--platform/android/java/app/src/com/godot/game/GodotApp.java11
-rw-r--r--platform/android/java/build.gradle12
-rw-r--r--platform/android/java/gradle.properties2
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--platform/android/java/lib/build.gradle54
-rw-r--r--platform/android/java/lib/res/layout/downloading_expansion.xml2
-rw-r--r--platform/android/java/lib/res/layout/godot_app_layout.xml5
-rw-r--r--platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml2
-rw-r--r--platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml2
-rw-r--r--platform/android/java/lib/res/values-fa/strings.xml1
-rw-r--r--platform/android/java/lib/res/values-in/strings.xml4
-rw-r--r--platform/android/java/lib/res/values-iw/strings.xml4
-rw-r--r--platform/android/java/lib/res/values-ko/strings.xml3
-rw-r--r--platform/android/java/lib/res/values/dimens.xml4
-rw-r--r--platform/android/java/lib/res/values/strings.xml2
-rw-r--r--platform/android/java/lib/res/values/styles.xml2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java (renamed from platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/CustomSSLSocketFactory.java)79
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java394
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java22
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java41
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java22
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java27
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java49
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java105
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java18
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java7
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java15
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt3
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt2
-rw-r--r--platform/android/java/nativeSrcsConfigs/AndroidManifest.xml2
-rw-r--r--platform/android/java/nativeSrcsConfigs/CMakeLists.txt (renamed from platform/android/java/lib/CMakeLists.txt)1
-rw-r--r--platform/android/java/nativeSrcsConfigs/README.md4
-rw-r--r--platform/android/java/nativeSrcsConfigs/build.gradle54
-rw-r--r--platform/android/java/plugins/godotpayment/build.gradle32
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml11
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl281
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ConsumeTask.java116
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java258
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/HandlePurchaseTask.java93
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsCache.java70
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsManager.java403
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java118
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ReleaseAllConsumablesTask.java140
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ValidateTask.java143
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/HttpRequester.java230
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/RequestParams.java84
-rw-r--r--platform/android/java/settings.gradle2
101 files changed, 898 insertions, 2390 deletions
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index f5b1d29f22..e94681659c 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -38,13 +38,16 @@
<activity
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
+ android:theme="@style/GodotAppSplashTheme"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:resizeableActivity="false"
tools:ignore="UnusedAttribute" >
+ <!-- Focus awareness metadata is updated at export time if the user enables it in the 'Xr Features' section. -->
+ <meta-data android:name="com.oculus.vr.focusaware" android:value="false" />
+
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index 19202d2310..53d11fda5b 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -70,8 +70,8 @@ android {
buildToolsVersion versions.buildTools
compileOptions {
- sourceCompatibility 1.8
- targetCompatibility 1.8
+ sourceCompatibility versions.javaVersion
+ targetCompatibility versions.javaVersion
}
defaultConfig {
@@ -80,8 +80,15 @@ android {
ignoreAssetsPattern "!.svn:!.git:!.ds_store:!*.scc:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
+ ndk {
+ String[] export_abi_list = getExportEnabledABIs()
+ abiFilters export_abi_list
+ }
+
// Feel free to modify the application id to your own.
applicationId getExportPackageName()
+ versionCode getExportVersionCode()
+ versionName getExportVersionName()
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
}
@@ -99,10 +106,41 @@ android {
// doNotStrip '**/*.so'
}
- // Both signing and zip-aligning will be done at export time
- buildTypes.all { buildType ->
- buildType.zipAlignEnabled false
- buildType.signingConfig null
+ signingConfigs {
+ release {
+ File keystoreFile = new File(getReleaseKeystoreFile())
+ if (keystoreFile.isFile()) {
+ storeFile keystoreFile
+ storePassword getReleaseKeystorePassword()
+ keyAlias getReleaseKeyAlias()
+ keyPassword getReleaseKeystorePassword()
+ }
+ }
+ }
+
+ buildTypes {
+
+ debug {
+ // Signing and zip-aligning are skipped for prebuilt builds, but
+ // performed for custom builds.
+ zipAlignEnabled shouldZipAlign()
+ if (shouldSign()) {
+ signingConfig signingConfigs.debug
+ } else {
+ signingConfig null
+ }
+ }
+
+ release {
+ // Signing and zip-aligning are skipped for prebuilt builds, but
+ // performed for custom builds.
+ zipAlignEnabled shouldZipAlign()
+ if (shouldSign()) {
+ signingConfig signingConfigs.release
+ } else {
+ signingConfig null
+ }
+ }
}
sourceSets {
@@ -123,3 +161,27 @@ android {
}
}
}
+
+task copyAndRenameDebugApk(type: Copy) {
+ from "$buildDir/outputs/apk/debug/android_debug.apk"
+ into getExportPath()
+ rename "android_debug.apk", getExportFilename()
+}
+
+task copyAndRenameReleaseApk(type: Copy) {
+ from "$buildDir/outputs/apk/release/android_release.apk"
+ into getExportPath()
+ rename "android_release.apk", getExportFilename()
+}
+
+task copyAndRenameDebugAab(type: Copy) {
+ from "$buildDir/outputs/bundle/debug/build-debug.aab"
+ into getExportPath()
+ rename "build-debug.aab", getExportFilename()
+}
+
+task copyAndRenameReleaseAab(type: Copy) {
+ from "$buildDir/outputs/bundle/release/build-release.aab"
+ into getExportPath()
+ rename "build-release.aab", getExportFilename()
+}
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index 5251bc3066..80cf6f7ede 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -1,12 +1,13 @@
ext.versions = [
- androidGradlePlugin: '3.5.3',
+ androidGradlePlugin: '4.1.0',
compileSdk : 29,
minSdk : 18,
targetSdk : 29,
- buildTools : '29.0.3',
+ buildTools : '30.0.1',
supportCoreUtils : '1.0.0',
- kotlinVersion : '1.3.61',
- v4Support : '1.0.0'
+ kotlinVersion : '1.4.10',
+ v4Support : '1.0.0',
+ javaVersion : 1.8
]
@@ -28,8 +29,59 @@ ext.getExportPackageName = { ->
return appId
}
+ext.getExportVersionCode = { ->
+ String versionCode = project.hasProperty("export_version_code") ? project.property("export_version_code") : ""
+ if (versionCode == null || versionCode.isEmpty()) {
+ versionCode = "1"
+ }
+ try {
+ return Integer.parseInt(versionCode)
+ } catch (NumberFormatException ignored) {
+ return 1
+ }
+}
+
+ext.getExportVersionName = { ->
+ String versionName = project.hasProperty("export_version_name") ? project.property("export_version_name") : ""
+ if (versionName == null || versionName.isEmpty()) {
+ versionName = "1.0"
+ }
+ return versionName
+}
+
final String PLUGIN_VALUE_SEPARATOR_REGEX = "\\|"
+// get the list of ABIs the project should be exported to
+ext.getExportEnabledABIs = { ->
+ String enabledABIs = project.hasProperty("export_enabled_abis") ? project.property("export_enabled_abis") : "";
+ if (enabledABIs == null || enabledABIs.isEmpty()) {
+ enabledABIs = "armeabi-v7a|arm64-v8a|x86|x86_64|"
+ }
+ Set<String> exportAbiFilter = [];
+ for (String abi_name : enabledABIs.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ if (!abi_name.trim().isEmpty()){
+ exportAbiFilter.add(abi_name);
+ }
+ }
+ return exportAbiFilter;
+}
+
+ext.getExportPath = {
+ String exportPath = project.hasProperty("export_path") ? project.property("export_path") : ""
+ if (exportPath == null || exportPath.isEmpty()) {
+ exportPath = "."
+ }
+ return exportPath
+}
+
+ext.getExportFilename = {
+ String exportFilename = project.hasProperty("export_filename") ? project.property("export_filename") : ""
+ if (exportFilename == null || exportFilename.isEmpty()) {
+ exportFilename = "godot_android"
+ }
+ return exportFilename
+}
+
/**
* Parse the project properties for the 'plugins_maven_repos' property and return the list
* of maven repos.
@@ -72,17 +124,12 @@ ext.getGodotPluginsRemoteBinaries = { ->
/**
* Parse the project properties for the 'plugins_local_binaries' property and return
* their binaries for inclusion in the build dependencies.
- *
- * Returns the prebuilt plugins if the 'plugins_local_binaries' property is unavailable.
*/
ext.getGodotPluginsLocalBinaries = { ->
- // Set the prebuilt plugins as default. If custom build is enabled,
- // the 'plugins_local_binaries' will be defined so we can use it instead.
- Set<String> binDeps = ["libs/plugins/GodotPayment.release.aar"]
+ Set<String> binDeps = []
// Retrieve the list of local plugins binaries.
if (project.hasProperty("plugins_local_binaries")) {
- binDeps.clear()
String pluginsList = project.property("plugins_local_binaries")
if (pluginsList != null && !pluginsList.trim().isEmpty()) {
for (String plugin : pluginsList.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
@@ -93,3 +140,37 @@ ext.getGodotPluginsLocalBinaries = { ->
return binDeps
}
+
+ext.getReleaseKeystoreFile = { ->
+ String keystoreFile = project.hasProperty("release_keystore_file") ? project.property("release_keystore_file") : ""
+ if (keystoreFile == null || keystoreFile.isEmpty()) {
+ keystoreFile = "."
+ }
+ return keystoreFile
+}
+
+ext.getReleaseKeystorePassword = { ->
+ String keystorePassword = project.hasProperty("release_keystore_password") ? project.property("release_keystore_password") : ""
+ return keystorePassword
+}
+
+ext.getReleaseKeyAlias = { ->
+ String keyAlias = project.hasProperty("release_keystore_alias") ? project.property("release_keystore_alias") : ""
+ return keyAlias
+}
+
+ext.shouldZipAlign = { ->
+ String zipAlignFlag = project.hasProperty("perform_zipalign") ? project.property("perform_zipalign") : ""
+ if (zipAlignFlag == null || zipAlignFlag.isEmpty()) {
+ zipAlignFlag = "false"
+ }
+ return Boolean.parseBoolean(zipAlignFlag)
+}
+
+ext.shouldSign = { ->
+ String signFlag = project.hasProperty("perform_signing") ? project.property("perform_signing") : ""
+ if (signFlag == null || signFlag.isEmpty()) {
+ signFlag = "false"
+ }
+ return Boolean.parseBoolean(signFlag)
+}
diff --git a/platform/android/java/app/res/drawable/splash.png b/platform/android/java/app/res/drawable/splash.png
new file mode 100644
index 0000000000..7bddd4325a
--- /dev/null
+++ b/platform/android/java/app/res/drawable/splash.png
Binary files differ
diff --git a/platform/android/java/app/res/drawable/splash_bg_color.png b/platform/android/java/app/res/drawable/splash_bg_color.png
new file mode 100644
index 0000000000..004b6fd508
--- /dev/null
+++ b/platform/android/java/app/res/drawable/splash_bg_color.png
Binary files differ
diff --git a/platform/android/java/app/res/drawable/splash_drawable.xml b/platform/android/java/app/res/drawable/splash_drawable.xml
new file mode 100644
index 0000000000..2794a40817
--- /dev/null
+++ b/platform/android/java/app/res/drawable/splash_drawable.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:drawable="@drawable/splash_bg_color" />
+
+ <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@drawable/splash" />
+ </item>
+
+</layer-list>
diff --git a/platform/android/java/lib/res/values-ar/strings.xml b/platform/android/java/app/res/values-ar/godot_project_name_string.xml
index 9f3dc6d6ac..23aa5cf3e1 100644
--- a/platform/android/java/lib/res/values-ar/strings.xml
+++ b/platform/android/java/app/res/values-ar/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-ar</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-bg/strings.xml b/platform/android/java/app/res/values-bg/godot_project_name_string.xml
index bd8109277e..dbb7e04ae5 100644
--- a/platform/android/java/lib/res/values-bg/strings.xml
+++ b/platform/android/java/app/res/values-bg/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-bg</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-ca/strings.xml b/platform/android/java/app/res/values-ca/godot_project_name_string.xml
index 494cb88468..709d0961e6 100644
--- a/platform/android/java/lib/res/values-ca/strings.xml
+++ b/platform/android/java/app/res/values-ca/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-ca</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-cs/strings.xml b/platform/android/java/app/res/values-cs/godot_project_name_string.xml
index 30ce00f895..ab248a8032 100644
--- a/platform/android/java/lib/res/values-cs/strings.xml
+++ b/platform/android/java/app/res/values-cs/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-cs</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-da/strings.xml b/platform/android/java/app/res/values-da/godot_project_name_string.xml
index 4c2a1cf0f4..906bf44f57 100644
--- a/platform/android/java/lib/res/values-da/strings.xml
+++ b/platform/android/java/app/res/values-da/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-da</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-de/strings.xml b/platform/android/java/app/res/values-de/godot_project_name_string.xml
index 52946d4cce..0cacb0175f 100644
--- a/platform/android/java/lib/res/values-de/strings.xml
+++ b/platform/android/java/app/res/values-de/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-de</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-el/strings.xml b/platform/android/java/app/res/values-el/godot_project_name_string.xml
index 181dc51762..047de616a5 100644
--- a/platform/android/java/lib/res/values-el/strings.xml
+++ b/platform/android/java/app/res/values-el/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-el</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-en/strings.xml b/platform/android/java/app/res/values-en/godot_project_name_string.xml
index 976a565013..bb3a5dbef3 100644
--- a/platform/android/java/lib/res/values-en/strings.xml
+++ b/platform/android/java/app/res/values-en/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-en</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-es-rES/strings.xml b/platform/android/java/app/res/values-es-rES/godot_project_name_string.xml
index 73f63a08f8..d4537f3496 100644
--- a/platform/android/java/lib/res/values-es-rES/strings.xml
+++ b/platform/android/java/app/res/values-es-rES/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-es_ES</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-es/strings.xml b/platform/android/java/app/res/values-es/godot_project_name_string.xml
index 07b718a641..d63a16022e 100644
--- a/platform/android/java/lib/res/values-es/strings.xml
+++ b/platform/android/java/app/res/values-es/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-es</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/app/res/values-fa/godot_project_name_string.xml b/platform/android/java/app/res/values-fa/godot_project_name_string.xml
new file mode 100644
index 0000000000..c303f13d5f
--- /dev/null
+++ b/platform/android/java/app/res/values-fa/godot_project_name_string.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
+<resources>
+ <string name="godot_project_name_string">godot-project-name-fa</string>
+</resources>
diff --git a/platform/android/java/lib/res/values-fi/strings.xml b/platform/android/java/app/res/values-fi/godot_project_name_string.xml
index 323d82aff1..bd6005574a 100644
--- a/platform/android/java/lib/res/values-fi/strings.xml
+++ b/platform/android/java/app/res/values-fi/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-fi</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-fr/strings.xml b/platform/android/java/app/res/values-fr/godot_project_name_string.xml
index 32bead2661..2e94b65a20 100644
--- a/platform/android/java/lib/res/values-fr/strings.xml
+++ b/platform/android/java/app/res/values-fr/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-fr</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-hi/strings.xml b/platform/android/java/app/res/values-hi/godot_project_name_string.xml
index 8aab2a8c63..0bf75dcd56 100644
--- a/platform/android/java/lib/res/values-hi/strings.xml
+++ b/platform/android/java/app/res/values-hi/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-hi</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-hr/strings.xml b/platform/android/java/app/res/values-hr/godot_project_name_string.xml
index caf55e2241..d3f75910f9 100644
--- a/platform/android/java/lib/res/values-hr/strings.xml
+++ b/platform/android/java/app/res/values-hr/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-hr</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-hu/strings.xml b/platform/android/java/app/res/values-hu/godot_project_name_string.xml
index e7f9e51226..012b613af3 100644
--- a/platform/android/java/lib/res/values-hu/strings.xml
+++ b/platform/android/java/app/res/values-hu/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-hu</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/app/res/values-in/godot_project_name_string.xml b/platform/android/java/app/res/values-in/godot_project_name_string.xml
new file mode 100644
index 0000000000..eedecff7a1
--- /dev/null
+++ b/platform/android/java/app/res/values-in/godot_project_name_string.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
+<resources>
+ <string name="godot_project_name_string">godot-project-name-in</string>
+</resources>
diff --git a/platform/android/java/lib/res/values-it/strings.xml b/platform/android/java/app/res/values-it/godot_project_name_string.xml
index 1f5e5a049e..7e734047c4 100644
--- a/platform/android/java/lib/res/values-it/strings.xml
+++ b/platform/android/java/app/res/values-it/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-it</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/app/res/values-iw/godot_project_name_string.xml b/platform/android/java/app/res/values-iw/godot_project_name_string.xml
new file mode 100644
index 0000000000..03893f0cbb
--- /dev/null
+++ b/platform/android/java/app/res/values-iw/godot_project_name_string.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
+<resources>
+ <string name="godot_project_name_string">godot-project-name-iw</string>
+</resources>
diff --git a/platform/android/java/lib/res/values-ja/strings.xml b/platform/android/java/app/res/values-ja/godot_project_name_string.xml
index 7f85f57df7..f9dd4fab0d 100644
--- a/platform/android/java/lib/res/values-ja/strings.xml
+++ b/platform/android/java/app/res/values-ja/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-ja</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/app/res/values-ko/godot_project_name_string.xml b/platform/android/java/app/res/values-ko/godot_project_name_string.xml
new file mode 100644
index 0000000000..26f5dac176
--- /dev/null
+++ b/platform/android/java/app/res/values-ko/godot_project_name_string.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
+<resources>
+ <string name="godot_project_name_string">godot-project-name-ko</string>
+</resources>
diff --git a/platform/android/java/lib/res/values-lt/strings.xml b/platform/android/java/app/res/values-lt/godot_project_name_string.xml
index 6e3677fde7..1c2e976cc5 100644
--- a/platform/android/java/lib/res/values-lt/strings.xml
+++ b/platform/android/java/app/res/values-lt/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-lt</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-lv/strings.xml b/platform/android/java/app/res/values-lv/godot_project_name_string.xml
index 701fc271ac..b5e638ed73 100644
--- a/platform/android/java/lib/res/values-lv/strings.xml
+++ b/platform/android/java/app/res/values-lv/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-lv</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-nb/strings.xml b/platform/android/java/app/res/values-nb/godot_project_name_string.xml
index 73147ca1af..e6d89d6a3f 100644
--- a/platform/android/java/lib/res/values-nb/strings.xml
+++ b/platform/android/java/app/res/values-nb/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-nb</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-nl/strings.xml b/platform/android/java/app/res/values-nl/godot_project_name_string.xml
index e501928a35..93cb3a3878 100644
--- a/platform/android/java/lib/res/values-nl/strings.xml
+++ b/platform/android/java/app/res/values-nl/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-nl</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-pl/strings.xml b/platform/android/java/app/res/values-pl/godot_project_name_string.xml
index ea5da73b6f..e5d6ac74fb 100644
--- a/platform/android/java/lib/res/values-pl/strings.xml
+++ b/platform/android/java/app/res/values-pl/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-pl</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-pt/strings.xml b/platform/android/java/app/res/values-pt/godot_project_name_string.xml
index bdda7cd2c7..a4624655c5 100644
--- a/platform/android/java/lib/res/values-pt/strings.xml
+++ b/platform/android/java/app/res/values-pt/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-pt</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-ro/strings.xml b/platform/android/java/app/res/values-ro/godot_project_name_string.xml
index 3686da4c19..19e026637e 100644
--- a/platform/android/java/lib/res/values-ro/strings.xml
+++ b/platform/android/java/app/res/values-ro/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-ro</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-ru/strings.xml b/platform/android/java/app/res/values-ru/godot_project_name_string.xml
index 954067658b..284845241f 100644
--- a/platform/android/java/lib/res/values-ru/strings.xml
+++ b/platform/android/java/app/res/values-ru/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-ru</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-sk/strings.xml b/platform/android/java/app/res/values-sk/godot_project_name_string.xml
index 37d1283124..f8ab4a5b59 100644
--- a/platform/android/java/lib/res/values-sk/strings.xml
+++ b/platform/android/java/app/res/values-sk/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-sk</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-sl/strings.xml b/platform/android/java/app/res/values-sl/godot_project_name_string.xml
index 0bb249c375..98bd53e8d2 100644
--- a/platform/android/java/lib/res/values-sl/strings.xml
+++ b/platform/android/java/app/res/values-sl/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-sl</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-sr/strings.xml b/platform/android/java/app/res/values-sr/godot_project_name_string.xml
index 0e83cab1a1..3f400f2a4d 100644
--- a/platform/android/java/lib/res/values-sr/strings.xml
+++ b/platform/android/java/app/res/values-sr/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-sr</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-sv/strings.xml b/platform/android/java/app/res/values-sv/godot_project_name_string.xml
index e3a04ac2ec..8670b7c9aa 100644
--- a/platform/android/java/lib/res/values-sv/strings.xml
+++ b/platform/android/java/app/res/values-sv/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-sv</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-th/strings.xml b/platform/android/java/app/res/values-th/godot_project_name_string.xml
index 0aa893b8bf..a1cc1bcd49 100644
--- a/platform/android/java/lib/res/values-th/strings.xml
+++ b/platform/android/java/app/res/values-th/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-th</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-tl/strings.xml b/platform/android/java/app/res/values-tl/godot_project_name_string.xml
index e7e2af4909..6d66d114cf 100644
--- a/platform/android/java/lib/res/values-tl/strings.xml
+++ b/platform/android/java/app/res/values-tl/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-tl</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-tr/strings.xml b/platform/android/java/app/res/values-tr/godot_project_name_string.xml
index 97af1243a6..ba3bd7de36 100644
--- a/platform/android/java/lib/res/values-tr/strings.xml
+++ b/platform/android/java/app/res/values-tr/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-tr</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-uk/strings.xml b/platform/android/java/app/res/values-uk/godot_project_name_string.xml
index 3dea6908a9..5f14ab25a0 100644
--- a/platform/android/java/lib/res/values-uk/strings.xml
+++ b/platform/android/java/app/res/values-uk/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-uk</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-vi/strings.xml b/platform/android/java/app/res/values-vi/godot_project_name_string.xml
index a6552130b0..295378e111 100644
--- a/platform/android/java/lib/res/values-vi/strings.xml
+++ b/platform/android/java/app/res/values-vi/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-vi</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values-zh-rHK/strings.xml b/platform/android/java/app/res/values-zh-rHK/godot_project_name_string.xml
index 8a6269da0f..40ab0f285a 100644
--- a/platform/android/java/lib/res/values-zh-rHK/strings.xml
+++ b/platform/android/java/app/res/values-zh-rHK/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-zh_HK</string>
</resources>
diff --git a/platform/android/java/lib/res/values-zh-rTW/strings.xml b/platform/android/java/app/res/values-zh-rTW/godot_project_name_string.xml
index b1bb39d5d6..095bd564e2 100644
--- a/platform/android/java/lib/res/values-zh-rTW/strings.xml
+++ b/platform/android/java/app/res/values-zh-rTW/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-zh_TW</string>
</resources>
diff --git a/platform/android/java/lib/res/values-zh-rCN/strings.xml b/platform/android/java/app/res/values-zh/godot_project_name_string.xml
index 6668c56bd9..31aa8c273a 100644
--- a/platform/android/java/lib/res/values-zh-rCN/strings.xml
+++ b/platform/android/java/app/res/values-zh/godot_project_name_string.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
<resources>
<string name="godot_project_name_string">godot-project-name-zh</string>
</resources>
diff --git a/platform/android/java/app/res/values/godot_project_name_string.xml b/platform/android/java/app/res/values/godot_project_name_string.xml
new file mode 100644
index 0000000000..7ec2738896
--- /dev/null
+++ b/platform/android/java/app/res/values/godot_project_name_string.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
+<resources>
+ <string name="godot_project_name_string">godot-project-name</string>
+</resources>
diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml
new file mode 100644
index 0000000000..99f723f5ba
--- /dev/null
+++ b/platform/android/java/app/res/values/themes.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="GodotAppMainTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen"/>
+
+ <style name="GodotAppSplashTheme" parent="@style/GodotAppMainTheme">
+ <item name="android:windowBackground">@drawable/splash_drawable</item>
+ <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
+ </style>
+</resources>
diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java
index eb884404cd..51df70969e 100644
--- a/platform/android/java/app/src/com/godot/game/GodotApp.java
+++ b/platform/android/java/app/src/com/godot/game/GodotApp.java
@@ -30,11 +30,18 @@
package com.godot.game;
-import org.godotengine.godot.Godot;
+import org.godotengine.godot.FullScreenGodotApp;
+
+import android.os.Bundle;
/**
* Template activity for Godot Android custom builds.
* Feel free to extend and modify this class for your custom logic.
*/
-public class GodotApp extends Godot {
+public class GodotApp extends FullScreenGodotApp {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ setTheme(R.style.GodotAppMainTheme);
+ super.onCreate(savedInstanceState);
+ }
}
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index 01a3607b20..73c136ed0e 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -22,8 +22,6 @@ allprojects {
}
ext {
- sconsExt = org.gradle.internal.os.OperatingSystem.current().isWindows() ? ".bat" : ""
-
supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"]
supportedTargets = ["release", "debug"]
@@ -97,13 +95,6 @@ task copyReleaseAARToAppModule(type: Copy) {
include('godot-lib.release.aar')
}
-task copyGodotPaymentPluginToAppModule(type: Copy) {
- dependsOn ':plugins:godotpayment:assembleRelease'
- from('plugins/godotpayment/build/outputs/aar')
- into('app/libs/plugins')
- include('GodotPayment.release.aar')
-}
-
/**
* Copy the Godot android library archive release file into the root bin directory.
* Depends on the library build task to ensure the AAR file is generated prior to copying.
@@ -161,7 +152,6 @@ task generateGodotTemplates(type: GradleBuild) {
}
}
- dependsOn 'copyGodotPaymentPluginToAppModule'
finalizedBy 'zipCustomBuild'
}
@@ -193,4 +183,6 @@ task cleanGodotTemplates(type: Delete) {
delete("$binDir/android_source.zip")
delete("$binDir/godot-lib.debug.aar")
delete("$binDir/godot-lib.release.aar")
+
+ finalizedBy getTasksByName("clean", true)
}
diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties
index e14cd5ba5c..2dc069ad2f 100644
--- a/platform/android/java/gradle.properties
+++ b/platform/android/java/gradle.properties
@@ -18,3 +18,5 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
+
+org.gradle.warning.mode=all
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
index f56b0f6a5e..a7d8a0f310 100644
--- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle
index 19eee5a315..89ce3d15e6 100644
--- a/platform/android/java/lib/build.gradle
+++ b/platform/android/java/lib/build.gradle
@@ -18,6 +18,11 @@ android {
targetSdkVersion versions.targetSdk
}
+ compileOptions {
+ sourceCompatibility versions.javaVersion
+ targetCompatibility versions.javaVersion
+ }
+
lintOptions {
abortOnError false
disable 'MissingTranslation', 'UnusedResources'
@@ -50,15 +55,6 @@ android {
def buildType = variant.buildType.name.capitalize()
- def taskPrefix = ""
- if (project.path != ":") {
- taskPrefix = project.path + ":"
- }
-
- // Disable the externalNativeBuild* task as it would cause build failures since the cmake build
- // files is only setup for editing support.
- gradle.startParameter.excludedTaskNames += taskPrefix + "externalNativeBuild" + buildType
-
def releaseTarget = buildType.toLowerCase()
if (releaseTarget == null || releaseTarget == "") {
throw new GradleException("Invalid build type: " + buildType)
@@ -68,20 +64,46 @@ android {
throw new GradleException("Invalid default abi: " + defaultAbi)
}
+ // Find scons' executable path
+ File sconsExecutableFile = null
+ def sconsName = "scons"
+ def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows()
+ ? [".bat", ".exe"]
+ : [""])
+ logger.lifecycle("Looking for $sconsName executable path")
+ for (ext in sconsExts) {
+ String sconsNameExt = sconsName + ext
+ logger.lifecycle("Checking $sconsNameExt")
+
+ sconsExecutableFile = org.gradle.internal.os.OperatingSystem.current().findInPath(sconsNameExt)
+ if (sconsExecutableFile != null) {
+ // We're done!
+ break
+ }
+
+ // Check all the options in path
+ List<File> allOptions = org.gradle.internal.os.OperatingSystem.current().findAllInPath(sconsNameExt)
+ if (!allOptions.isEmpty()) {
+ // Pick the first option and we're done!
+ sconsExecutableFile = allOptions.get(0)
+ break
+ }
+ }
+
+ if (sconsExecutableFile == null) {
+ throw new GradleException("Unable to find executable path for the '$sconsName' command.")
+ } else {
+ logger.lifecycle("Found executable path for $sconsName: ${sconsExecutableFile.absolutePath}")
+ }
+
// Creating gradle task to generate the native libraries for the default abi.
def taskName = getSconsTaskName(buildType)
tasks.create(name: taskName, type: Exec) {
- executable "scons" + sconsExt
+ executable sconsExecutableFile.absolutePath
args "--directory=${pathToRootDir}", "platform=android", "target=${releaseTarget}", "android_arch=${defaultAbi}", "-j" + Runtime.runtime.availableProcessors()
}
// Schedule the tasks so the generated libs are present before the aar file is packaged.
tasks["merge${buildType}JniLibFolders"].dependsOn taskName
}
-
- externalNativeBuild {
- cmake {
- path "CMakeLists.txt"
- }
- }
}
diff --git a/platform/android/java/lib/res/layout/downloading_expansion.xml b/platform/android/java/lib/res/layout/downloading_expansion.xml
index 4a9700965f..34c2757598 100644
--- a/platform/android/java/lib/res/layout/downloading_expansion.xml
+++ b/platform/android/java/lib/res/layout/downloading_expansion.xml
@@ -162,4 +162,4 @@
</LinearLayout>
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/platform/android/java/lib/res/layout/godot_app_layout.xml b/platform/android/java/lib/res/layout/godot_app_layout.xml
new file mode 100644
index 0000000000..386ded1c5d
--- /dev/null
+++ b/platform/android/java/lib/res/layout/godot_app_layout.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/godot_fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
index fae1faeb60..426e1bd841 100644
--- a/platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
+++ b/platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
@@ -105,4 +105,4 @@
</RelativeLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
index 1ed4037035..cfdcca2ab5 100644
--- a/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
+++ b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
@@ -2,4 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/icon_background"/>
<foreground android:drawable="@mipmap/icon_foreground"/>
-</adaptive-icon> \ No newline at end of file
+</adaptive-icon>
diff --git a/platform/android/java/lib/res/values-fa/strings.xml b/platform/android/java/lib/res/values-fa/strings.xml
index f1e29013c4..60b01accf1 100644
--- a/platform/android/java/lib/res/values-fa/strings.xml
+++ b/platform/android/java/lib/res/values-fa/strings.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="godot_project_name_string">godot-project-name-fa</string>
<string name="text_paused_cellular">آیا می خواهید بر روی اتصال داده همراه دانلود را شروع کنید؟ بر اساس نوع سطح داده شما این ممکن است برای شما هزینه مالی داشته باشد.</string>
<string name="text_paused_cellular_2">اگر نمی خواهید بر روی اتصال داده همراه دانلود را شروع کنید ، دانلود به صورت خودکار در زمان دسترسی به وای-فای شروع می شود.</string>
<string name="text_button_resume_cellular">ادامه دانلود</string>
diff --git a/platform/android/java/lib/res/values-in/strings.xml b/platform/android/java/lib/res/values-in/strings.xml
deleted file mode 100644
index 9e9a8b0c03..0000000000
--- a/platform/android/java/lib/res/values-in/strings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="godot_project_name_string">godot-project-name-id</string>
-</resources> \ No newline at end of file
diff --git a/platform/android/java/lib/res/values-iw/strings.xml b/platform/android/java/lib/res/values-iw/strings.xml
deleted file mode 100644
index f52ede2085..0000000000
--- a/platform/android/java/lib/res/values-iw/strings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="godot_project_name_string">godot-project-name-he</string>
-</resources> \ No newline at end of file
diff --git a/platform/android/java/lib/res/values-ko/strings.xml b/platform/android/java/lib/res/values-ko/strings.xml
index fab0bdd753..7b62345977 100644
--- a/platform/android/java/lib/res/values-ko/strings.xml
+++ b/platform/android/java/lib/res/values-ko/strings.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="godot_project_name_string">godot-project-name-ko</string>
<string name="text_paused_cellular">모바일 네트워크를 사용하여 다운로드 하시겠습니까? 남은 데이터 사용량에 따라, 요금이 부과될 수 있습니다.</string>
<string name="text_paused_cellular_2">모바일 네트워크를 사용하여 다운로드 하지 않을 경우, 와이파이 연결이 가능할 때 자동적으로 다운로드가 이루어집니다.</string>
<string name="text_button_resume_cellular">다운로드 계속하기</string>
@@ -52,4 +51,4 @@
<string name="kilobytes_per_second">%1$s KB/s</string>
<string name="time_remaining">남은 시간: %1$s</string>
<string name="time_remaining_notification">%1$s 남음</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values/dimens.xml b/platform/android/java/lib/res/values/dimens.xml
new file mode 100644
index 0000000000..9034dbbcc1
--- /dev/null
+++ b/platform/android/java/lib/res/values/dimens.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="text_edit_height">48dp</dimen>
+</resources>
diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml
index a1b81a6186..590b066d8a 100644
--- a/platform/android/java/lib/res/values/strings.xml
+++ b/platform/android/java/lib/res/values/strings.xml
@@ -52,4 +52,4 @@
<string name="kilobytes_per_second">%1$s KB/s</string>
<string name="time_remaining">Time remaining: %1$s</string>
<string name="time_remaining_notification">%1$s left</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/lib/res/values/styles.xml b/platform/android/java/lib/res/values/styles.xml
index a442f61e7e..b798373bc6 100644
--- a/platform/android/java/lib/res/values/styles.xml
+++ b/platform/android/java/lib/res/values/styles.xml
@@ -22,4 +22,4 @@
<item name="android:background">@android:color/background_dark</item>
</style>
-</resources> \ No newline at end of file
+</resources>
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/CustomSSLSocketFactory.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
index 55b87b49e5..5aa48d87da 100644
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* CustomSSLSocketFactory.java */
+/* FullScreenGodotApp.java */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,45 +28,72 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-package org.godotengine.godot.plugin.payment.utils;
+package org.godotengine.godot;
-import java.io.IOException;
-import java.net.Socket;
-import java.net.UnknownHostException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.http.conn.ssl.SSLSocketFactory;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
/**
+ * Base activity for Android apps intending to use Godot as the primary and only screen.
*
- * @author Luis Linietsky <luis.linietsky@gmail.com>
+ * It's also a reference implementation for how to setup and use the {@link Godot} fragment
+ * within an Android app.
*/
-public class CustomSSLSocketFactory extends SSLSocketFactory {
- SSLContext sslContext = SSLContext.getInstance("TLS");
+public abstract class FullScreenGodotApp extends FragmentActivity {
+ @Nullable
+ private Godot godotFragment;
- public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- super(truststore);
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.godot_app_layout);
+ godotFragment = initGodotInstance();
+ if (godotFragment == null) {
+ throw new IllegalStateException("Godot instance must be non-null.");
+ }
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
- tmf.init(truststore);
+ getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss();
+ }
- sslContext.init(null, tmf.getTrustManagers(), null);
+ @Override
+ public void onNewIntent(Intent intent) {
+ if (godotFragment != null) {
+ godotFragment.onNewIntent(intent);
+ }
}
@Override
- public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
- return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
+ public void onBackPressed() {
+ if (godotFragment != null) {
+ godotFragment.onBackPressed();
+ } else {
+ super.onBackPressed();
+ }
}
@Override
- public Socket createSocket() throws IOException {
- return sslContext.getSocketFactory().createSocket();
+ public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
+ if (godotFragment != null && godotFragment.onKeyMultiple(inKeyCode, repeatCount, event)) {
+ return true;
+ }
+ return super.onKeyMultiple(inKeyCode, repeatCount, event);
+ }
+
+ /**
+ * Used to initialize the Godot fragment instance in {@link FullScreenGodotApp#onCreate(Bundle)}.
+ */
+ @NonNull
+ protected Godot initGodotInstance() {
+ return new Godot();
+ }
+
+ @Nullable
+ protected final Godot getGodotFragment() {
+ return godotFragment;
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index f27d8620ec..3bbe35091c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -30,6 +30,9 @@
package org.godotengine.godot;
+import static android.content.Context.MODE_PRIVATE;
+import static android.content.Context.WINDOW_SERVICE;
+
import org.godotengine.godot.input.GodotEditText;
import org.godotengine.godot.plugin.GodotPlugin;
import org.godotengine.godot.plugin.GodotPluginRegistry;
@@ -67,7 +70,9 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings.Secure;
import android.view.Display;
+import android.view.InputDevice;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -84,7 +89,7 @@ import android.widget.TextView;
import androidx.annotation.CallSuper;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
-import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.Fragment;
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
@@ -102,7 +107,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-public abstract class Godot extends FragmentActivity implements SensorEventListener, IDownloaderClient {
+public class Godot extends Fragment implements SensorEventListener, IDownloaderClient {
private IStub mDownloaderClientStub;
private TextView mStatusText;
private TextView mProgressFraction;
@@ -130,7 +135,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
static private Intent mCurrentIntent;
- @Override
public void onNewIntent(Intent intent) {
mCurrentIntent = intent;
}
@@ -148,14 +152,14 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
private void setButtonPausedState(boolean paused) {
mStatePaused = paused;
- int stringResourceID = paused ? R.string.text_button_resume :
- R.string.text_button_pause;
+ int stringResourceID = paused ? R.string.text_button_resume : R.string.text_button_pause;
mPauseButton.setText(stringResourceID);
}
private String[] command_line;
private boolean use_apk_expansion;
+ private ViewGroup containerLayout;
public GodotRenderView mRenderView;
private boolean godot_initialized = false;
@@ -174,7 +178,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
public ResultCallback result_callback;
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (result_callback != null) {
result_callback.callback(requestCode, resultCode, data);
result_callback = null;
@@ -211,27 +215,29 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
*/
@Keep
private void onVideoInit() {
- final FrameLayout layout = new FrameLayout(this);
- layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- setContentView(layout);
+ final Activity activity = getActivity();
+ containerLayout = new FrameLayout(activity);
+ containerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// GodotEditText layout
- GodotEditText editText = new GodotEditText(this);
- editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+ GodotEditText editText = new GodotEditText(activity);
+ editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
+ (int)getResources().getDimension(R.dimen.text_edit_height)));
// ...add to FrameLayout
- layout.addView(editText);
+ containerLayout.addView(editText);
GodotLib.setup(command_line);
final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name");
if (videoDriver.equals("Vulkan")) {
- mRenderView = new GodotVulkanRenderView(this);
+ mRenderView = new GodotVulkanRenderView(activity, this);
} else {
- mRenderView = new GodotGLRenderView(this, xrMode, use_32_bits, use_debug_opengl);
+ mRenderView = new GodotGLRenderView(activity, this, xrMode, use_32_bits,
+ use_debug_opengl);
}
View view = mRenderView.getView();
- layout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+ containerLayout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
editText.setView(mRenderView);
io.setEdit(editText);
@@ -239,7 +245,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
@Override
public void onGlobalLayout() {
Point fullSize = new Point();
- getWindowManager().getDefaultDisplay().getSize(fullSize);
+ activity.getWindowManager().getDefaultDisplay().getSize(fullSize);
Rect gameSize = new Rect();
mRenderView.getView().getWindowVisibleDisplayFrame(gameSize);
@@ -262,9 +268,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
// Include the returned non-null views in the Godot view hierarchy.
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
- View pluginView = plugin.onMainCreateView(this);
+ View pluginView = plugin.onMainCreate(activity);
if (pluginView != null) {
- layout.addView(pluginView);
+ containerLayout.addView(pluginView);
}
}
}
@@ -274,9 +280,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
@Override
public void run() {
if (p_enabled) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else {
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
});
@@ -290,7 +296,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
@Keep
private void vibrate(int durationMs) {
if (requestPermission("VIBRATE")) {
- Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
+ Vibrator v = (Vibrator)getContext().getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE));
@@ -314,13 +320,16 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
// Using instrumentation is a way of making the whole app process restart, because Android
// will kill any process of the same package which was already running.
//
- Bundle args = new Bundle();
- args.putParcelable("intent", mCurrentIntent);
- startInstrumentation(new ComponentName(this, GodotInstrumentation.class), null, args);
+ final Activity activity = getActivity();
+ if (activity != null) {
+ Bundle args = new Bundle();
+ args.putParcelable("intent", mCurrentIntent);
+ activity.startInstrumentation(new ComponentName(activity, GodotInstrumentation.class), null, args);
+ }
}
public void alert(final String message, final String title) {
- final Activity activity = this;
+ final Activity activity = getActivity();
runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -340,15 +349,16 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
public int getGLESVersionCode() {
- ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
+ ActivityManager am = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo deviceInfo = am.getDeviceConfigurationInfo();
return deviceInfo.reqGlEsVersion;
}
- private String[] getCommandLine() {
+ @CallSuper
+ protected String[] getCommandLine() {
InputStream is;
try {
- is = getAssets().open("_cl_");
+ is = getActivity().getAssets().open("_cl_");
byte[] len = new byte[4];
int r = is.read(len);
if (r < 4) {
@@ -425,11 +435,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
command_line = new_cmdline;
}
- io = new GodotIO(this);
- io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
+ final Activity activity = getActivity();
+ io = new GodotIO(activity);
+ io.unique_id = Secure.getString(activity.getContentResolver(), Secure.ANDROID_ID);
GodotLib.io = io;
- netUtils = new GodotNetUtils(this);
- mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ netUtils = new GodotNetUtils(activity);
+ mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
@@ -439,7 +450,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
- GodotLib.initialize(this, getAssets(), use_apk_expansion);
+ GodotLib.initialize(activity, this, activity.getAssets(), use_apk_expansion);
result_callback = null;
@@ -453,151 +464,152 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
@Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- Window window = getWindow();
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) {
+ final Activity activity = getActivity();
+ Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
- mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
+ mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
//check for apk expansion API
- if (true) {
- boolean md5mismatch = false;
- command_line = getCommandLine();
- String main_pack_md5 = null;
- String main_pack_key = null;
-
- List<String> new_args = new LinkedList<String>();
-
- for (int i = 0; i < command_line.length; i++) {
- boolean has_extra = i < command_line.length - 1;
- if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) {
- xrMode = XRMode.REGULAR;
- } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) {
- xrMode = XRMode.OVR;
- } else if (command_line[i].equals("--use_depth_32")) {
- use_32_bits = true;
- } else if (command_line[i].equals("--debug_opengl")) {
- use_debug_opengl = true;
- } else if (command_line[i].equals("--use_immersive")) {
- use_immersive = true;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
- window.getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
- View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
-
- UiChangeListener();
- }
- } else if (command_line[i].equals("--use_apk_expansion")) {
- use_apk_expansion = true;
- } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) {
- main_pack_md5 = command_line[i + 1];
- i++;
- } else if (has_extra && command_line[i].equals("--apk_expansion_key")) {
- main_pack_key = command_line[i + 1];
- SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE);
- Editor editor = prefs.edit();
- editor.putString("store_public_key", main_pack_key);
-
- editor.apply();
- i++;
- } else if (command_line[i].trim().length() != 0) {
- new_args.add(command_line[i]);
+ boolean md5mismatch = false;
+ command_line = getCommandLine();
+ String main_pack_md5 = null;
+ String main_pack_key = null;
+
+ List<String> new_args = new LinkedList<String>();
+
+ for (int i = 0; i < command_line.length; i++) {
+ boolean has_extra = i < command_line.length - 1;
+ if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) {
+ xrMode = XRMode.REGULAR;
+ } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) {
+ xrMode = XRMode.OVR;
+ } else if (command_line[i].equals("--use_depth_32")) {
+ use_32_bits = true;
+ } else if (command_line[i].equals("--debug_opengl")) {
+ use_debug_opengl = true;
+ } else if (command_line[i].equals("--use_immersive")) {
+ use_immersive = true;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
+ window.getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+ View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+ UiChangeListener();
}
+ } else if (command_line[i].equals("--use_apk_expansion")) {
+ use_apk_expansion = true;
+ } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) {
+ main_pack_md5 = command_line[i + 1];
+ i++;
+ } else if (has_extra && command_line[i].equals("--apk_expansion_key")) {
+ main_pack_key = command_line[i + 1];
+ SharedPreferences prefs = activity.getSharedPreferences("app_data_keys",
+ MODE_PRIVATE);
+ Editor editor = prefs.edit();
+ editor.putString("store_public_key", main_pack_key);
+
+ editor.apply();
+ i++;
+ } else if (command_line[i].trim().length() != 0) {
+ new_args.add(command_line[i]);
}
+ }
- if (new_args.isEmpty()) {
- command_line = null;
- } else {
- command_line = new_args.toArray(new String[new_args.size()]);
+ if (new_args.isEmpty()) {
+ command_line = null;
+ } else {
+ command_line = new_args.toArray(new String[new_args.size()]);
+ }
+ if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
+ //check that environment is ok!
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ //show popup and die
}
- if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
- //check that environment is ok!
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- //show popup and die
- }
- // Build the full path to the app's expansion files
- try {
- expansion_pack_path = Helpers.getSaveFilePath(getApplicationContext());
- expansion_pack_path += "/main." + getPackageManager().getPackageInfo(getPackageName(), 0).versionCode + "." + this.getPackageName() + ".obb";
- } catch (Exception e) {
- e.printStackTrace();
- }
+ // Build the full path to the app's expansion files
+ try {
+ expansion_pack_path = Helpers.getSaveFilePath(getContext());
+ expansion_pack_path += "/main." + activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0).versionCode + "." + activity.getPackageName() + ".obb";
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
- File f = new File(expansion_pack_path);
+ File f = new File(expansion_pack_path);
- boolean pack_valid = true;
+ boolean pack_valid = true;
- if (!f.exists()) {
- pack_valid = false;
+ if (!f.exists()) {
+ pack_valid = false;
- } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) {
- pack_valid = false;
- try {
- f.delete();
- } catch (Exception e) {
- }
+ } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) {
+ pack_valid = false;
+ try {
+ f.delete();
+ } catch (Exception e) {
}
+ }
- if (!pack_valid) {
- Intent notifierIntent = new Intent(this, this.getClass());
- notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ if (!pack_valid) {
+ Intent notifierIntent = new Intent(activity, activity.getClass());
+ notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_CLEAR_TOP);
- PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
- notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0,
+ notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- int startResult;
- try {
- startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
- getApplicationContext(),
- pendingIntent,
+ int startResult;
+ try {
+ startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
+ getContext(),
+ pendingIntent,
+ GodotDownloaderService.class);
+
+ if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
+ // This is where you do set up to display the download
+ // progress (next step)
+ mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
GodotDownloaderService.class);
- if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
- // This is where you do set up to display the download
- // progress (next step)
- mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
- GodotDownloaderService.class);
-
- setContentView(R.layout.downloading_expansion);
- mPB = (ProgressBar)findViewById(R.id.progressBar);
- mStatusText = (TextView)findViewById(R.id.statusText);
- mProgressFraction = (TextView)findViewById(R.id.progressAsFraction);
- mProgressPercent = (TextView)findViewById(R.id.progressAsPercentage);
- mAverageSpeed = (TextView)findViewById(R.id.progressAverageSpeed);
- mTimeRemaining = (TextView)findViewById(R.id.progressTimeRemaining);
- mDashboard = findViewById(R.id.downloaderDashboard);
- mCellMessage = findViewById(R.id.approveCellular);
- mPauseButton = (Button)findViewById(R.id.pauseButton);
- mWiFiSettingsButton = (Button)findViewById(R.id.wifiSettingsButton);
-
- return;
- }
- } catch (NameNotFoundException e) {
- // TODO Auto-generated catch block
+ View downloadingExpansionView =
+ inflater.inflate(R.layout.downloading_expansion, container, false);
+ mPB = (ProgressBar)downloadingExpansionView.findViewById(R.id.progressBar);
+ mStatusText = (TextView)downloadingExpansionView.findViewById(R.id.statusText);
+ mProgressFraction = (TextView)downloadingExpansionView.findViewById(R.id.progressAsFraction);
+ mProgressPercent = (TextView)downloadingExpansionView.findViewById(R.id.progressAsPercentage);
+ mAverageSpeed = (TextView)downloadingExpansionView.findViewById(R.id.progressAverageSpeed);
+ mTimeRemaining = (TextView)downloadingExpansionView.findViewById(R.id.progressTimeRemaining);
+ mDashboard = downloadingExpansionView.findViewById(R.id.downloaderDashboard);
+ mCellMessage = downloadingExpansionView.findViewById(R.id.approveCellular);
+ mPauseButton = (Button)downloadingExpansionView.findViewById(R.id.pauseButton);
+ mWiFiSettingsButton = (Button)downloadingExpansionView.findViewById(R.id.wifiSettingsButton);
+
+ return downloadingExpansionView;
}
+ } catch (NameNotFoundException e) {
+ // TODO Auto-generated catch block
}
}
}
- mCurrentIntent = getIntent();
+ mCurrentIntent = activity.getIntent();
initializeGodot();
+ return containerLayout;
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onMainDestroy();
}
- GodotLib.ondestroy(this);
+ GodotLib.ondestroy();
super.onDestroy();
@@ -607,13 +619,13 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
activityResumed = false;
if (!godot_initialized) {
if (null != mDownloaderClientStub) {
- mDownloaderClientStub.disconnect(this);
+ mDownloaderClientStub.disconnect(getActivity());
}
return;
}
@@ -643,12 +655,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
activityResumed = true;
if (!godot_initialized) {
if (null != mDownloaderClientStub) {
- mDownloaderClientStub.connect(this);
+ mDownloaderClientStub.connect(getActivity());
}
return;
}
@@ -661,7 +673,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
if (use_immersive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
- Window window = getWindow();
+ Window window = getActivity().getWindow();
window.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
@@ -677,7 +689,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
public void UiChangeListener() {
- final View decorView = getWindow().getDecorView();
+ final View decorView = getActivity().getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
@@ -698,7 +710,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
@Override
public void onSensorChanged(SensorEvent event) {
- Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
+ Display display =
+ ((WindowManager)getActivity().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int displayRotation = display.getRotation();
float[] adjustedValues = new float[3];
@@ -747,9 +760,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
/*
@Override public boolean dispatchKeyEvent(KeyEvent event) {
-
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
-
System.out.printf("** BACK REQUEST!\n");
GodotLib.quit();
@@ -761,7 +772,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
*/
- @Override
public void onBackPressed() {
boolean shouldQuit = true;
@@ -792,6 +802,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
}
+ public final void runOnUiThread(@NonNull Runnable action) {
+ if (getActivity() != null) {
+ getActivity().runOnUiThread(action);
+ }
+ }
+
private void forceQuit() {
System.exit(0);
}
@@ -837,75 +853,17 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
}
- public boolean gotTouchEvent(final MotionEvent event) {
- final int evcount = event.getPointerCount();
- if (evcount == 0)
- return true;
-
- if (mRenderView != null) {
- final int[] arr = new int[event.getPointerCount() * 3];
-
- for (int i = 0; i < event.getPointerCount(); i++) {
- arr[i * 3 + 0] = (int)event.getPointerId(i);
- arr[i * 3 + 1] = (int)event.getX(i);
- arr[i * 3 + 2] = (int)event.getY(i);
- }
- final int pointer_idx = event.getPointerId(event.getActionIndex());
-
- //System.out.printf("gaction: %d\n",event.getAction());
- final int action = event.getAction() & MotionEvent.ACTION_MASK;
- mRenderView.queueOnRenderThread(new Runnable() {
- @Override
- public void run() {
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- GodotLib.touch(0, 0, evcount, arr);
- //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
- } break;
- case MotionEvent.ACTION_MOVE: {
- GodotLib.touch(1, 0, evcount, arr);
- /*
- for(int i=0;i<event.getPointerCount();i++) {
- System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
- }
- */
- } break;
- case MotionEvent.ACTION_POINTER_UP: {
- GodotLib.touch(4, pointer_idx, evcount, arr);
- //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
- } break;
- case MotionEvent.ACTION_POINTER_DOWN: {
- GodotLib.touch(3, pointer_idx, evcount, arr);
- //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
- } break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
- GodotLib.touch(2, 0, evcount, arr);
- /*
- for(int i=0;i<event.getPointerCount();i++) {
- System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
- }
- */
- } break;
- }
- }
- });
- }
- return true;
- }
-
- @Override
public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
String s = event.getCharacters();
if (s == null || s.length() == 0)
- return super.onKeyMultiple(inKeyCode, repeatCount, event);
+ return false;
final char[] cc = s.toCharArray();
int cnt = 0;
for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
;
if (cnt == 0)
- return super.onKeyMultiple(inKeyCode, repeatCount, event);
+ return false;
mRenderView.queueOnRenderThread(new Runnable() {
// This method will be called on the rendering thread:
public void run() {
@@ -923,15 +881,15 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
}
public boolean requestPermission(String p_name) {
- return PermissionsUtil.requestPermission(p_name, this);
+ return PermissionsUtil.requestPermission(p_name, getActivity());
}
public boolean requestPermissions() {
- return PermissionsUtil.requestManifestPermissions(this);
+ return PermissionsUtil.requestManifestPermissions(getActivity());
}
public String[] getGrantedPermissions() {
- return PermissionsUtil.getGrantedPermissions(this);
+ return PermissionsUtil.getGrantedPermissions(getActivity());
}
/**
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index 14dd893faa..d731e080c4 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -29,7 +29,6 @@
/*************************************************************************/
package org.godotengine.godot;
-
import org.godotengine.godot.input.GodotGestureHandler;
import org.godotengine.godot.input.GodotInputHandler;
import org.godotengine.godot.utils.GLUtils;
@@ -42,6 +41,7 @@ import org.godotengine.godot.xr.regular.RegularContextFactory;
import org.godotengine.godot.xr.regular.RegularFallbackConfigChooser;
import android.annotation.SuppressLint;
+import android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.view.GestureDetector;
@@ -68,19 +68,20 @@ import android.view.SurfaceView;
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
- private final Godot activity;
+ private final Godot godot;
private final GodotInputHandler inputHandler;
private final GestureDetector detector;
private final GodotRenderer godotRenderer;
- public GodotGLRenderView(Godot activity, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) {
- super(activity);
+ public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_32_bits,
+ boolean p_use_debug_opengl) {
+ super(context);
GLUtils.use_32 = p_use_32_bits;
GLUtils.use_debug_opengl = p_use_debug_opengl;
- this.activity = activity;
+ this.godot = godot;
this.inputHandler = new GodotInputHandler(this);
- this.detector = new GestureDetector(activity, new GodotGestureHandler(this));
+ this.detector = new GestureDetector(context, new GodotGestureHandler(this));
this.godotRenderer = new GodotRenderer();
init(xrMode, false, 16, 0);
}
@@ -112,7 +113,12 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
@Override
public void onBackPressed() {
- activity.onBackPressed();
+ godot.onBackPressed();
+ }
+
+ @Override
+ public GodotInputHandler getInputHandler() {
+ return inputHandler;
}
@SuppressLint("ClickableViewAccessibility")
@@ -120,7 +126,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
this.detector.onTouchEvent(event);
- return activity.gotTouchEvent(event);
+ return inputHandler.onTouchEvent(event);
}
@Override
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 93f4786e83..894009e30f 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -32,16 +32,21 @@ package org.godotengine.godot;
import org.godotengine.godot.input.*;
+import android.app.Activity;
import android.content.*;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
+import android.graphics.Point;
import android.media.*;
import android.net.Uri;
import android.os.*;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayCutout;
+import android.view.WindowInsets;
import java.io.IOException;
import java.io.InputStream;
@@ -51,7 +56,7 @@ import java.util.Locale;
public class GodotIO {
AssetManager am;
- Godot activity;
+ final Activity activity;
GodotEditText edit;
final int SCREEN_LANDSCAPE = 0;
@@ -314,7 +319,7 @@ public class GodotIO {
dirs.remove(id);
}
- GodotIO(Godot p_activity) {
+ GodotIO(Activity p_activity) {
am = p_activity.getAssets();
activity = p_activity;
//streams = new HashMap<Integer, AssetData>();
@@ -460,9 +465,31 @@ public class GodotIO {
return (int)(metrics.density * 160f);
}
- public void showKeyboard(String p_existing_text, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ public int[] screenGetUsableRect() {
+ DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
+ Display display = activity.getWindowManager().getDefaultDisplay();
+ Point size = new Point();
+ display.getRealSize(size);
+
+ int result[] = { 0, 0, size.x, size.y };
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets();
+ DisplayCutout cutout = insets.getDisplayCutout();
+ if (cutout != null) {
+ int insetLeft = cutout.getSafeInsetLeft();
+ int insetTop = cutout.getSafeInsetTop();
+ result[0] = insetLeft;
+ result[1] = insetTop;
+ result[2] -= insetLeft + cutout.getSafeInsetRight();
+ result[3] -= insetTop + cutout.getSafeInsetBottom();
+ }
+ }
+ return result;
+ }
+
+ public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
if (edit != null)
- edit.showKeyboard(p_existing_text, p_max_input_length, p_cursor_start, p_cursor_end);
+ edit.showKeyboard(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
@@ -488,13 +515,13 @@ public class GodotIO {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} break;
case SCREEN_SENSOR_LANDSCAPE: {
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
} break;
case SCREEN_SENSOR_PORTRAIT: {
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
} break;
case SCREEN_SENSOR: {
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
} break;
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 3693f36557..6ccbe91e60 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -50,13 +50,13 @@ public class GodotLib {
/**
* Invoked on the main thread to initialize Godot native layer.
*/
- public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion);
+ public static native void initialize(Activity activity, Godot p_instance, Object p_asset_manager, boolean use_apk_expansion);
/**
* Invoked on the main thread to clean up Godot native layer.
- * @see Activity#onDestroy()
+ * @see androidx.fragment.app.Fragment#onDestroy()
*/
- public static native void ondestroy(Godot p_instance);
+ public static native void ondestroy();
/**
* Invoked on the GL thread to complete setup for the Godot native layer logic.
@@ -94,17 +94,19 @@ public class GodotLib {
/**
* Forward touch events from the main thread to the GL thread.
*/
- public static native void touch(int what, int pointer, int howmany, int[] arr);
+ public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions);
+ public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions, int buttonsMask);
+ public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions, int buttonsMask, float verticalFactor, float horizontalFactor);
/**
* Forward hover events from the main thread to the GL thread.
*/
- public static native void hover(int type, int x, int y);
+ public static native void hover(int type, float x, float y);
/**
* Forward double_tap events from the main thread to the GL thread.
*/
- public static native void doubletap(int x, int y);
+ public static native void doubleTap(int buttonMask, int x, int y);
/**
* Forward scroll events from the main thread to the GL thread.
@@ -161,14 +163,14 @@ public class GodotLib {
public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
/**
- * Invoked when the Android activity resumes.
- * @see Activity#onResume()
+ * Invoked when the Android app resumes.
+ * @see androidx.fragment.app.Fragment#onResume()
*/
public static native void focusin();
/**
- * Invoked when the Android activity pauses.
- * @see Activity#onPause()
+ * Invoked when the Android app pauses.
+ * @see androidx.fragment.app.Fragment#onPause()
*/
public static native void focusout();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
index 27e63f3a66..68b8a16641 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
@@ -30,6 +30,8 @@
package org.godotengine.godot;
+import org.godotengine.godot.input.GodotInputHandler;
+
import android.view.SurfaceView;
public interface GodotRenderView {
@@ -43,4 +45,6 @@ public interface GodotRenderView {
abstract public void onActivityResumed();
abstract public void onBackPressed();
+
+ abstract public GodotInputHandler getInputHandler();
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index e9872b58ff..6cd5ca7b4e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -36,23 +36,25 @@ import org.godotengine.godot.vulkan.VkRenderer;
import org.godotengine.godot.vulkan.VkSurfaceView;
import android.annotation.SuppressLint;
+import android.content.Context;
import android.view.GestureDetector;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceView;
public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
- private final Godot mActivity;
+ private final Godot godot;
private final GodotInputHandler mInputHandler;
private final GestureDetector mGestureDetector;
private final VkRenderer mRenderer;
- public GodotVulkanRenderView(Godot activity) {
- super(activity);
+ public GodotVulkanRenderView(Context context, Godot godot) {
+ super(context);
- mActivity = activity;
+ this.godot = godot;
mInputHandler = new GodotInputHandler(this);
- mGestureDetector = new GestureDetector(mActivity, new GodotGestureHandler(this));
+ mGestureDetector = new GestureDetector(context, new GodotGestureHandler(this));
mRenderer = new VkRenderer();
setFocusableInTouchMode(true);
@@ -86,7 +88,12 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
@Override
public void onBackPressed() {
- mActivity.onBackPressed();
+ godot.onBackPressed();
+ }
+
+ @Override
+ public GodotInputHandler getInputHandler() {
+ return mInputHandler;
}
@SuppressLint("ClickableViewAccessibility")
@@ -94,22 +101,22 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
mGestureDetector.onTouchEvent(event);
- return mActivity.gotTouchEvent(event);
+ return mInputHandler.onTouchEvent(event);
}
@Override
public boolean onKeyUp(final int keyCode, KeyEvent event) {
- return mInputHandler.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
+ return mInputHandler.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(final int keyCode, KeyEvent event) {
- return mInputHandler.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
+ return mInputHandler.onKeyDown(keyCode, event);
}
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
- return mInputHandler.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
+ return mInputHandler.onGenericMotionEvent(event);
}
@Override
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
index 7f596575a8..c95339c583 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
@@ -36,6 +36,7 @@ import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.InputFilter;
+import android.text.InputType;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
@@ -58,7 +59,8 @@ public class GodotEditText extends EditText {
private GodotTextInputWrapper mInputWrapper;
private EditHandler sHandler = new EditHandler(this);
private String mOriginText;
- private int mMaxInputLength;
+ private int mMaxInputLength = Integer.MAX_VALUE;
+ private boolean mMultiline = false;
private static class EditHandler extends Handler {
private final WeakReference<GodotEditText> mEdit;
@@ -95,7 +97,11 @@ public class GodotEditText extends EditText {
protected void initView() {
setPadding(0, 0, 0, 0);
- setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+ setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_DONE);
+ }
+
+ public boolean isMultiline() {
+ return mMultiline;
}
private void handleMessage(final Message msg) {
@@ -115,6 +121,12 @@ public class GodotEditText extends EditText {
edit.mInputWrapper.setSelection(false);
}
+ int inputType = InputType.TYPE_CLASS_TEXT;
+ if (edit.isMultiline()) {
+ inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+ }
+ edit.setInputType(inputType);
+
edit.mInputWrapper.setOriginText(text);
edit.addTextChangedListener(edit.mInputWrapper);
final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -155,20 +167,41 @@ public class GodotEditText extends EditText {
// ===========================================================
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
- super.onKeyDown(keyCode, keyEvent);
-
- /* Let GlSurfaceView get focus if back key is input. */
+ /* Let SurfaceView get focus if back key is input. */
if (keyCode == KeyEvent.KEYCODE_BACK) {
mRenderView.getView().requestFocus();
}
- return true;
+ // pass event to godot in special cases
+ if (needHandlingInGodot(keyCode, keyEvent) && mRenderView.getInputHandler().onKeyDown(keyCode, keyEvent)) {
+ return true;
+ } else {
+ return super.onKeyDown(keyCode, keyEvent);
+ }
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
+ if (needHandlingInGodot(keyCode, keyEvent) && mRenderView.getInputHandler().onKeyUp(keyCode, keyEvent)) {
+ return true;
+ } else {
+ return super.onKeyUp(keyCode, keyEvent);
+ }
+ }
+
+ private boolean needHandlingInGodot(int keyCode, KeyEvent keyEvent) {
+ boolean isArrowKey = keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN ||
+ keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT;
+ boolean isModifiedKey = keyEvent.isAltPressed() || keyEvent.isCtrlPressed() || keyEvent.isSymPressed() ||
+ keyEvent.isFunctionPressed() || keyEvent.isMetaPressed();
+ return isArrowKey || keyCode == KeyEvent.KEYCODE_TAB || KeyEvent.isModifierKey(keyCode) ||
+ isModifiedKey;
}
// ===========================================================
// Methods
// ===========================================================
- public void showKeyboard(String p_existing_text, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length;
if (p_cursor_start == -1) { // cursor position not given
this.mOriginText = p_existing_text;
@@ -181,6 +214,8 @@ public class GodotEditText extends EditText {
this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_end);
}
+ this.mMultiline = p_multiline;
+
final Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
msg.obj = this;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
index 1c9a683bbd..fb151fa504 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
@@ -33,7 +33,6 @@ package org.godotengine.godot.input;
import org.godotengine.godot.GodotLib;
import org.godotengine.godot.GodotRenderView;
-import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
@@ -75,10 +74,11 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener
//Log.i("GodotGesture", "onDoubleTap");
final int x = Math.round(event.getX());
final int y = Math.round(event.getY());
+ final int buttonMask = event.getButtonState();
queueEvent(new Runnable() {
@Override
public void run() {
- GodotLib.doubletap(x, y);
+ GodotLib.doubleTap(buttonMask, x, y);
}
});
return true;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index 9abd65cc67..f3e985f944 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -36,6 +36,7 @@ import org.godotengine.godot.GodotLib;
import org.godotengine.godot.GodotRenderView;
import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
+import android.os.Build;
import android.util.Log;
import android.view.InputDevice;
import android.view.InputDevice.MotionRange;
@@ -156,6 +157,53 @@ public class GodotInputHandler implements InputDeviceListener {
return true;
}
+ public boolean onTouchEvent(final MotionEvent event) {
+ // Mouse drag (mouse pressed and move) doesn't fire onGenericMotionEvent so this is needed
+ if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+ if (event.getAction() != MotionEvent.ACTION_MOVE) {
+ // we return true because every time a mouse event is fired, the event is already handled
+ // in onGenericMotionEvent, so by touch event we can say that the event is also handled
+ return true;
+ }
+ return handleMouseEvent(event);
+ }
+
+ final int evcount = event.getPointerCount();
+ if (evcount == 0)
+ return true;
+
+ if (mRenderView != null) {
+ final float[] arr = new float[event.getPointerCount() * 3]; // pointerId1, x1, y1, pointerId2, etc...
+
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ arr[i * 3 + 0] = event.getPointerId(i);
+ arr[i * 3 + 1] = event.getX(i);
+ arr[i * 3 + 2] = event.getY(i);
+ }
+ final int action = event.getActionMasked();
+
+ mRenderView.queueOnRenderThread(new Runnable() {
+ @Override
+ public void run() {
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_MOVE: {
+ GodotLib.touch(event.getSource(), action, 0, evcount, arr);
+ } break;
+ case MotionEvent.ACTION_POINTER_UP:
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ int pointer_idx = event.getPointerId(event.getActionIndex());
+ GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr);
+ } break;
+ }
+ }
+ });
+ }
+ return true;
+ }
+
public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
final int device_id = findJoystickDevice(event.getDeviceId());
@@ -189,8 +237,8 @@ public class GodotInputHandler implements InputDeviceListener {
return true;
}
} else if ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) {
- final int x = Math.round(event.getX());
- final int y = Math.round(event.getY());
+ final float x = event.getX();
+ final float y = event.getY();
final int type = event.getAction();
queueEvent(new Runnable() {
@Override
@@ -199,6 +247,10 @@ public class GodotInputHandler implements InputDeviceListener {
}
});
return true;
+ } else if ((event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return handleMouseEvent(event);
+ }
}
return false;
@@ -366,4 +418,53 @@ public class GodotInputHandler implements InputDeviceListener {
return -1;
}
+
+ private boolean handleMouseEvent(final MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ case MotionEvent.ACTION_HOVER_MOVE:
+ case MotionEvent.ACTION_HOVER_EXIT: {
+ final float x = event.getX();
+ final float y = event.getY();
+ final int type = event.getAction();
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.hover(type, x, y);
+ }
+ });
+ return true;
+ }
+ case MotionEvent.ACTION_BUTTON_PRESS:
+ case MotionEvent.ACTION_BUTTON_RELEASE:
+ case MotionEvent.ACTION_MOVE: {
+ final float x = event.getX();
+ final float y = event.getY();
+ final int buttonsMask = event.getButtonState();
+ final int action = event.getAction();
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask);
+ }
+ });
+ return true;
+ }
+ case MotionEvent.ACTION_SCROLL: {
+ final float x = event.getX();
+ final float y = event.getY();
+ final int buttonsMask = event.getButtonState();
+ final int action = event.getAction();
+ final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+ final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor);
+ }
+ });
+ }
+ }
+ return false;
+ }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 9c7cf9f341..4dd1054738 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -123,7 +123,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
public void run() {
for (int i = 0; i < count; ++i) {
int key = newChars[i];
- if (key == '\n') {
+ if ((key == '\n') && !mEdit.isMultiline()) {
// Return keys are handled through action events
continue;
}
@@ -151,7 +151,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
});
}
- if (pActionID == EditorInfo.IME_NULL) {
+ if (pActionID == EditorInfo.IME_ACTION_DONE) {
// Enter key has been pressed
GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true);
GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
index 431bd4f5f9..93c204935c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
@@ -35,6 +35,7 @@ import org.godotengine.godot.Godot;
import android.app.Activity;
import android.content.Intent;
+import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.View;
@@ -93,6 +94,14 @@ public abstract class GodotPlugin {
}
/**
+ * Provides access to the underlying {@link Activity}.
+ */
+ @Nullable
+ protected Activity getActivity() {
+ return godot.getActivity();
+ }
+
+ /**
* Register the plugin with Godot native code.
*
* This method is invoked on the render thread.
@@ -145,13 +154,14 @@ public abstract class GodotPlugin {
* Invoked once during the Godot Android initialization process after creation of the
* {@link org.godotengine.godot.GodotView} view.
* <p>
- * This method should be overridden by descendants of this class that would like to add
- * their view/layout to the Godot view hierarchy.
+ * The plugin can return a non-null {@link View} layout in order to add it to the Godot view
+ * hierarchy.
*
- * @return the view to be included; null if no views should be included.
+ * @see Activity#onCreate(Bundle)
+ * @return the plugin's view to be included; null if no views should be included.
*/
@Nullable
- public View onMainCreateView(Activity activity) {
+ public View onMainCreate(Activity activity) {
return null;
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
index 12d2ed09fb..1c2d1a6563 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
@@ -32,6 +32,7 @@ package org.godotengine.godot.plugin;
import org.godotengine.godot.Godot;
+import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
@@ -121,9 +122,11 @@ public final class GodotPluginRegistry {
private void loadPlugins(Godot godot) {
try {
- ApplicationInfo appInfo = godot
+ final Activity activity = godot.getActivity();
+ ApplicationInfo appInfo = activity
.getPackageManager()
- .getApplicationInfo(godot.getPackageName(), PackageManager.GET_META_DATA);
+ .getApplicationInfo(activity.getPackageName(),
+ PackageManager.GET_META_DATA);
Bundle metaData = appInfo.metaData;
if (metaData == null || metaData.isEmpty()) {
return;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java
index 0832a9b965..c89118ad55 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java
@@ -30,8 +30,7 @@
package org.godotengine.godot.utils;
-import org.godotengine.godot.Godot;
-
+import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.util.Log;
@@ -45,7 +44,7 @@ public class GodotNetUtils {
/* A single, reference counted, multicast lock, or null if permission CHANGE_WIFI_MULTICAST_STATE is missing */
private WifiManager.MulticastLock multicastLock;
- public GodotNetUtils(Godot p_activity) {
+ public GodotNetUtils(Activity p_activity) {
if (PermissionsUtil.hasManifestPermission(p_activity, "android.permission.CHANGE_WIFI_MULTICAST_STATE")) {
WifiManager wifi = (WifiManager)p_activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
multicastLock = wifi.createMulticastLock("GodotMulticastLock");
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
index 6837e4f147..7104baf86e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
@@ -30,9 +30,8 @@
package org.godotengine.godot.utils;
-import org.godotengine.godot.Godot;
-
import android.Manifest;
+import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
@@ -65,7 +64,7 @@ public final class PermissionsUtil {
* @param activity the caller activity for this method.
* @return true/false. "true" if permission was granted otherwise returns "false".
*/
- public static boolean requestPermission(String name, Godot activity) {
+ public static boolean requestPermission(String name, Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Not necessary, asked on install already
return true;
@@ -93,7 +92,7 @@ public final class PermissionsUtil {
* @param activity the caller activity for this method.
* @return true/false. "true" if all permissions were granted otherwise returns "false".
*/
- public static boolean requestManifestPermissions(Godot activity) {
+ public static boolean requestManifestPermissions(Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
@@ -138,7 +137,7 @@ public final class PermissionsUtil {
* @param activity the caller activity for this method.
* @return granted permissions list
*/
- public static String[] getGrantedPermissions(Godot activity) {
+ public static String[] getGrantedPermissions(Activity activity) {
String[] manifestPermissions;
try {
manifestPermissions = getManifestPermissions(activity);
@@ -172,7 +171,7 @@ public final class PermissionsUtil {
* @param permission the permession to look for in the manifest file.
* @return "true" if the permission is in the manifest file of the activity, "false" otherwise.
*/
- public static boolean hasManifestPermission(Godot activity, String permission) {
+ public static boolean hasManifestPermission(Activity activity, String permission) {
try {
for (String p : getManifestPermissions(activity)) {
if (permission.equals(p))
@@ -190,7 +189,7 @@ public final class PermissionsUtil {
* @return manifest permissions list
* @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found.
*/
- private static String[] getManifestPermissions(Godot activity) throws PackageManager.NameNotFoundException {
+ private static String[] getManifestPermissions(Activity activity) throws PackageManager.NameNotFoundException {
PackageManager packageManager = activity.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
if (packageInfo.requestedPermissions == null)
@@ -205,7 +204,7 @@ public final class PermissionsUtil {
* @return permission info object
* @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found.
*/
- private static PermissionInfo getPermissionInfo(Godot activity, String permission) throws PackageManager.NameNotFoundException {
+ private static PermissionInfo getPermissionInfo(Activity activity, String permission) throws PackageManager.NameNotFoundException {
PackageManager packageManager = activity.getPackageManager();
return packageManager.getPermissionInfo(permission, 0);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
index aeb4628d5d..f93cf0fa38 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
@@ -52,7 +52,6 @@ import org.godotengine.godot.plugin.GodotPluginRegistry
* @see [VkSurfaceView.startRenderer]
*/
internal class VkRenderer {
-
private val pluginRegistry: GodotPluginRegistry = GodotPluginRegistry.getPluginRegistry()
/**
@@ -71,7 +70,7 @@ internal class VkRenderer {
*/
fun onVkSurfaceChanged(surface: Surface, width: Int, height: Int) {
GodotLib.resize(surface, width, height)
-
+
for (plugin in pluginRegistry.getAllPlugins()) {
plugin.onVkSurfaceChanged(surface, width, height)
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
index 6b0e12b21a..e5c7a39bfb 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
@@ -50,7 +50,6 @@ import android.view.SurfaceView
* </ul>
*/
open internal class VkSurfaceView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {
-
companion object {
fun checkState(expression: Boolean, errorMessage: Any) {
check(expression) { errorMessage.toString() }
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
index 7557c8aa22..fb02e3a69f 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
@@ -41,7 +41,6 @@ import kotlin.concurrent.withLock
* The implementation is modeled after [android.opengl.GLSurfaceView]'s GLThread.
*/
internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vkRenderer: VkRenderer) : Thread(TAG) {
-
companion object {
private val TAG = VkThread::class.java.simpleName
}
@@ -226,5 +225,4 @@ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vk
threadExiting()
}
}
-
}
diff --git a/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml b/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml
new file mode 100644
index 0000000000..dc180375d5
--- /dev/null
+++ b/platform/android/java/nativeSrcsConfigs/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="org.godotengine.godot" />
diff --git a/platform/android/java/lib/CMakeLists.txt b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt
index d3bdf6a5f2..34925684da 100644
--- a/platform/android/java/lib/CMakeLists.txt
+++ b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt
@@ -1,3 +1,4 @@
+# Non functional cmake build file used to provide Android Studio editor support to the project.
cmake_minimum_required(VERSION 3.6)
project(godot)
diff --git a/platform/android/java/nativeSrcsConfigs/README.md b/platform/android/java/nativeSrcsConfigs/README.md
new file mode 100644
index 0000000000..e48505ccda
--- /dev/null
+++ b/platform/android/java/nativeSrcsConfigs/README.md
@@ -0,0 +1,4 @@
+## Native sources configs
+
+This is a non functional Android library used to provide Android Studio editor support to the Godot project native files.
+Nothing else should be added to this library.
diff --git a/platform/android/java/nativeSrcsConfigs/build.gradle b/platform/android/java/nativeSrcsConfigs/build.gradle
new file mode 100644
index 0000000000..65b7bb9dc9
--- /dev/null
+++ b/platform/android/java/nativeSrcsConfigs/build.gradle
@@ -0,0 +1,54 @@
+// Non functional android library used to provide Android Studio editor support to the project.
+plugins {
+ id 'com.android.library'
+}
+
+android {
+ compileSdkVersion versions.compileSdk
+ buildToolsVersion versions.buildTools
+
+ defaultConfig {
+ minSdkVersion versions.minSdk
+ targetSdkVersion versions.targetSdk
+ }
+
+ compileOptions {
+ sourceCompatibility versions.javaVersion
+ targetCompatibility versions.javaVersion
+ }
+
+ packagingOptions {
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/NOTICE'
+
+ // Should be uncommented for development purpose within Android Studio
+ // doNotStrip '**/*.so'
+ }
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "CMakeLists.txt"
+ }
+ }
+
+ libraryVariants.all { variant ->
+ def buildType = variant.buildType.name.capitalize()
+
+ def taskPrefix = ""
+ if (project.path != ":") {
+ taskPrefix = project.path + ":"
+ }
+
+ // Disable the externalNativeBuild* task as it would cause build failures since the cmake build
+ // files is only setup for editing support.
+ gradle.startParameter.excludedTaskNames += taskPrefix + "externalNativeBuild" + buildType
+ }
+}
+
+dependencies {}
diff --git a/platform/android/java/plugins/godotpayment/build.gradle b/platform/android/java/plugins/godotpayment/build.gradle
deleted file mode 100644
index ffab86e26e..0000000000
--- a/platform/android/java/plugins/godotpayment/build.gradle
+++ /dev/null
@@ -1,32 +0,0 @@
-apply plugin: 'com.android.library'
-
-android {
- compileSdkVersion versions.compileSdk
- buildToolsVersion versions.buildTools
- useLibrary 'org.apache.http.legacy'
-
- defaultConfig {
- minSdkVersion versions.minSdk
- targetSdkVersion versions.targetSdk
- }
-
- libraryVariants.all { variant ->
- variant.outputs.all { output ->
- output.outputFileName = "GodotPayment.${variant.name}.aar"
- }
- }
-
-}
-
-dependencies {
- implementation libraries.supportCoreUtils
- implementation libraries.v4Support
-
- if (rootProject.findProject(":lib")) {
- compileOnly project(":lib")
- } else if (rootProject.findProject(":godot:lib")) {
- compileOnly project(":godot:lib")
- } else {
- compileOnly fileTree(dir: 'libs', include: ['godot-lib*.aar'])
- }
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml b/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml
deleted file mode 100644
index 61afa03799..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.godotengine.godot.plugin.payment">
-
- <application>
-
- <meta-data
- android:name="org.godotengine.plugin.v1.GodotPayment"
- android:value="org.godotengine.godot.plugin.payment.GodotPayment" />
-
- </application>
-</manifest>
diff --git a/platform/android/java/plugins/godotpayment/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl b/platform/android/java/plugins/godotpayment/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
deleted file mode 100644
index 0f2bcae338..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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.android.vending.billing;
-
-import android.os.Bundle;
-
-/**
- * InAppBillingService is the service that provides in-app billing version 3 and beyond.
- * This service provides the following features:
- * 1. Provides a new API to get details of in-app items published for the app including
- * price, type, title and description.
- * 2. The purchase flow is synchronous and purchase information is available immediately
- * after it completes.
- * 3. Purchase information of in-app purchases is maintained within the Google Play system
- * till the purchase is consumed.
- * 4. An API to consume a purchase of an inapp item. All purchases of one-time
- * in-app items are consumable and thereafter can be purchased again.
- * 5. An API to get current purchases of the user immediately. This will not contain any
- * consumed purchases.
- *
- * All calls will give a response code with the following possible values
- * RESULT_OK = 0 - success
- * RESULT_USER_CANCELED = 1 - User pressed back or canceled a dialog
- * RESULT_SERVICE_UNAVAILABLE = 2 - The network connection is down
- * RESULT_BILLING_UNAVAILABLE = 3 - This billing API version is not supported for the type requested
- * RESULT_ITEM_UNAVAILABLE = 4 - Requested SKU is not available for purchase
- * RESULT_DEVELOPER_ERROR = 5 - Invalid arguments provided to the API
- * RESULT_ERROR = 6 - Fatal error during the API action
- * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
- * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
- */
-interface IInAppBillingService {
- /**
- * Checks support for the requested billing API version, package and in-app type.
- * Minimum API version supported by this interface is 3.
- * @param apiVersion billing API version that the app is using
- * @param packageName the package name of the calling app
- * @param type type of the in-app item being purchased ("inapp" for one-time purchases
- * and "subs" for subscriptions)
- * @return RESULT_OK(0) on success and appropriate response code on failures.
- */
- int isBillingSupported(int apiVersion, String packageName, String type);
-
- /**
- * Provides details of a list of SKUs
- * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
- * with a list JSON strings containing the productId, price, title and description.
- * This API can be called with a maximum of 20 SKUs.
- * @param apiVersion billing API version that the app is using
- * @param packageName the package name of the calling app
- * @param type of the in-app items ("inapp" for one-time purchases
- * and "subs" for subscriptions)
- * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes
- * on failures.
- * "DETAILS_LIST" with a StringArrayList containing purchase information
- * in JSON format similar to:
- * '{ "productId" : "exampleSku",
- * "type" : "inapp",
- * "price" : "$5.00",
- * "price_currency": "USD",
- * "price_amount_micros": 5000000,
- * "title : "Example Title",
- * "description" : "This is an example description" }'
- */
- Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
-
- /**
- * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
- * the type, a unique purchase token and an optional developer payload.
- * @param apiVersion billing API version that the app is using
- * @param packageName package name of the calling app
- * @param sku the SKU of the in-app item as published in the developer console
- * @param type of the in-app item being purchased ("inapp" for one-time purchases
- * and "subs" for subscriptions)
- * @param developerPayload optional argument to be sent back with the purchase information
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes
- * on failures.
- * "BUY_INTENT" - PendingIntent to start the purchase flow
- *
- * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
- * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
- * If the purchase is successful, the result data will contain the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response
- * codes on failures.
- * "INAPP_PURCHASE_DATA" - String in JSON format similar to
- * '{"orderId":"12999763169054705758.1371079406387615",
- * "packageName":"com.example.app",
- * "productId":"exampleSku",
- * "purchaseTime":1345678900000,
- * "purchaseToken" : "122333444455555",
- * "developerPayload":"example developer payload" }'
- * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
- * was signed with the private key of the developer
- */
- Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
- String developerPayload);
-
- /**
- * Returns the current SKUs owned by the user of the type and package name specified along with
- * purchase information and a signature of the data to be validated.
- * This will return all SKUs that have been purchased in V3 and managed items purchased using
- * V1 and V2 that have not been consumed.
- * @param apiVersion billing API version that the app is using
- * @param packageName package name of the calling app
- * @param type of the in-app items being requested ("inapp" for one-time purchases
- * and "subs" for subscriptions)
- * @param continuationToken to be set as null for the first call, if the number of owned
- * skus are too many, a continuationToken is returned in the response bundle.
- * This method can be called again with the continuation token to get the next set of
- * owned skus.
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes
- on failures.
- * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
- * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
- * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
- * of the purchase information
- * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
- * next set of in-app purchases. Only set if the
- * user has more owned skus than the current list.
- */
- Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
-
- /**
- * Consume the last purchase of the given SKU. This will result in this item being removed
- * from all subsequent responses to getPurchases() and allow re-purchase of this item.
- * @param apiVersion billing API version that the app is using
- * @param packageName package name of the calling app
- * @param purchaseToken token in the purchase information JSON that identifies the purchase
- * to be consumed
- * @return RESULT_OK(0) if consumption succeeded, appropriate response codes on failures.
- */
- int consumePurchase(int apiVersion, String packageName, String purchaseToken);
-
- /**
- * This API is currently under development.
- */
- int stub(int apiVersion, String packageName, String type);
-
- /**
- * Returns a pending intent to launch the purchase flow for upgrading or downgrading a
- * subscription. The existing owned SKU(s) should be provided along with the new SKU that
- * the user is upgrading or downgrading to.
- * @param apiVersion billing API version that the app is using, must be 5 or later
- * @param packageName package name of the calling app
- * @param oldSkus the SKU(s) that the user is upgrading or downgrading from,
- * if null or empty this method will behave like {@link #getBuyIntent}
- * @param newSku the SKU that the user is upgrading or downgrading to
- * @param type of the item being purchased, currently must be "subs"
- * @param developerPayload optional argument to be sent back with the purchase information
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes
- * on failures.
- * "BUY_INTENT" - PendingIntent to start the purchase flow
- *
- * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
- * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
- * If the purchase is successful, the result data will contain the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response
- * codes on failures.
- * "INAPP_PURCHASE_DATA" - String in JSON format similar to
- * '{"orderId":"12999763169054705758.1371079406387615",
- * "packageName":"com.example.app",
- * "productId":"exampleSku",
- * "purchaseTime":1345678900000,
- * "purchaseToken" : "122333444455555",
- * "developerPayload":"example developer payload" }'
- * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
- * was signed with the private key of the developer
- */
- Bundle getBuyIntentToReplaceSkus(int apiVersion, String packageName,
- in List<String> oldSkus, String newSku, String type, String developerPayload);
-
- /**
- * Returns a pending intent to launch the purchase flow for an in-app item. This method is
- * a variant of the {@link #getBuyIntent} method and takes an additional {@code extraParams}
- * parameter. This parameter is a Bundle of optional keys and values that affect the
- * operation of the method.
- * @param apiVersion billing API version that the app is using, must be 6 or later
- * @param packageName package name of the calling app
- * @param sku the SKU of the in-app item as published in the developer console
- * @param type of the in-app item being purchased ("inapp" for one-time purchases
- * and "subs" for subscriptions)
- * @param developerPayload optional argument to be sent back with the purchase information
- * @extraParams a Bundle with the following optional keys:
- * "skusToReplace" - List<String> - an optional list of SKUs that the user is
- * upgrading or downgrading from.
- * Pass this field if the purchase is upgrading or downgrading
- * existing subscriptions.
- * The specified SKUs are replaced with the SKUs that the user is
- * purchasing. Google Play replaces the specified SKUs at the start of
- * the next billing cycle.
- * "replaceSkusProration" - Boolean - whether the user should be credited for any unused
- * subscription time on the SKUs they are upgrading or downgrading.
- * If you set this field to true, Google Play swaps out the old SKUs
- * and credits the user with the unused value of their subscription
- * time on a pro-rated basis.
- * Google Play applies this credit to the new subscription, and does
- * not begin billing the user for the new subscription until after
- * the credit is used up.
- * If you set this field to false, the user does not receive credit for
- * any unused subscription time and the recurrence date does not
- * change.
- * Default value is true. Ignored if you do not pass skusToReplace.
- * "accountId" - String - an optional obfuscated string that is uniquely
- * associated with the user's account in your app.
- * If you pass this value, Google Play can use it to detect irregular
- * activity, such as many devices making purchases on the same
- * account in a short period of time.
- * Do not use the developer ID or the user's Google ID for this field.
- * In addition, this field should not contain the user's ID in
- * cleartext.
- * We recommend that you use a one-way hash to generate a string from
- * the user's ID, and store the hashed string in this field.
- * "vr" - Boolean - an optional flag indicating whether the returned intent
- * should start a VR purchase flow. The apiVersion must also be 7 or
- * later to use this flag.
- */
- Bundle getBuyIntentExtraParams(int apiVersion, String packageName, String sku,
- String type, String developerPayload, in Bundle extraParams);
-
- /**
- * Returns the most recent purchase made by the user for each SKU, even if that purchase is
- * expired, canceled, or consumed.
- * @param apiVersion billing API version that the app is using, must be 6 or later
- * @param packageName package name of the calling app
- * @param type of the in-app items being requested ("inapp" for one-time purchases
- * and "subs" for subscriptions)
- * @param continuationToken to be set as null for the first call, if the number of owned
- * skus is too large, a continuationToken is returned in the response bundle.
- * This method can be called again with the continuation token to get the next set of
- * owned skus.
- * @param extraParams a Bundle with extra params that would be appended into http request
- * query string. Not used at this moment. Reserved for future functionality.
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value: RESULT_OK(0) if success,
- * {@link IabHelper#BILLING_RESPONSE_RESULT_*} response codes on failures.
- *
- * "INAPP_PURCHASE_ITEM_LIST" - ArrayList<String> containing the list of SKUs
- * "INAPP_PURCHASE_DATA_LIST" - ArrayList<String> containing the purchase information
- * "INAPP_DATA_SIGNATURE_LIST"- ArrayList<String> containing the signatures
- * of the purchase information
- * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
- * next set of in-app purchases. Only set if the
- * user has more owned skus than the current list.
- */
- Bundle getPurchaseHistory(int apiVersion, String packageName, String type,
- String continuationToken, in Bundle extraParams);
-
- /**
- * This method is a variant of {@link #isBillingSupported}} that takes an additional
- * {@code extraParams} parameter.
- * @param apiVersion billing API version that the app is using, must be 7 or later
- * @param packageName package name of the calling app
- * @param type of the in-app item being purchased ("inapp" for one-time purchases and "subs"
- * for subscriptions)
- * @param extraParams a Bundle with the following optional keys:
- * "vr" - Boolean - an optional flag to indicate whether {link #getBuyIntentExtraParams}
- * supports returning a VR purchase flow.
- * @return RESULT_OK(0) on success and appropriate response code on failures.
- */
- int isBillingSupportedExtraParams(int apiVersion, String packageName, String type,
- in Bundle extraParams);
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ConsumeTask.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ConsumeTask.java
deleted file mode 100644
index de009f6d16..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ConsumeTask.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*************************************************************************/
-/* ConsumeTask.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.RemoteException;
-
-import com.android.vending.billing.IInAppBillingService;
-
-import java.lang.ref.WeakReference;
-
-abstract public class ConsumeTask {
- private Context context;
- private IInAppBillingService mService;
-
- private String mSku;
- private String mToken;
-
- private static class ConsumeAsyncTask extends AsyncTask<String, String, String> {
- private WeakReference<ConsumeTask> mTask;
-
- ConsumeAsyncTask(ConsumeTask consume) {
- mTask = new WeakReference<>(consume);
- }
-
- @Override
- protected String doInBackground(String... strings) {
- ConsumeTask consume = mTask.get();
- if (consume != null) {
- return consume.doInBackground(strings);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(String param) {
- ConsumeTask consume = mTask.get();
- if (consume != null) {
- consume.onPostExecute(param);
- }
- }
- }
-
- public ConsumeTask(IInAppBillingService mService, Context context) {
- this.context = context;
- this.mService = mService;
- }
-
- public void consume(final String sku) {
- mSku = sku;
- PaymentsCache pc = new PaymentsCache(context);
- Boolean isBlocked = pc.getConsumableFlag("block", sku);
- mToken = pc.getConsumableValue("token", sku);
- if (!isBlocked && mToken == null) {
- // Consuming task is processing
- } else if (!isBlocked) {
- return;
- } else if (mToken == null) {
- this.error("No token for sku:" + sku);
- return;
- }
- new ConsumeAsyncTask(this).execute();
- }
-
- private String doInBackground(String... params) {
- try {
- int response = mService.consumePurchase(3, context.getPackageName(), mToken);
- if (response == 0 || response == 8) {
- return null;
- }
- } catch (RemoteException e) {
- return e.getMessage();
- }
- return "Some error";
- }
-
- private void onPostExecute(String param) {
- if (param == null) {
- success(new PaymentsCache(context).getConsumableValue("ticket", mSku));
- } else {
- error(param);
- }
- }
-
- abstract protected void success(String ticket);
- abstract protected void error(String message);
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java
deleted file mode 100644
index e2b12c94a4..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*************************************************************************/
-/* GodotPayment.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import org.godotengine.godot.Dictionary;
-import org.godotengine.godot.Godot;
-import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.plugin.GodotPlugin;
-
-import android.content.Intent;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class GodotPayment extends GodotPlugin {
- private Long purchaseCallbackId = 0L;
- private String accessToken;
- private String purchaseValidationUrlPrefix;
- private String transactionId;
- private final PaymentsManager mPaymentManager;
- private final Dictionary mSkuDetails = new Dictionary();
-
- public GodotPayment(Godot godot) {
- super(godot);
- mPaymentManager = new PaymentsManager(godot, this);
- mPaymentManager.initService();
- }
-
- @Override
- public void onMainActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE) {
- mPaymentManager.processPurchaseResponse(resultCode, data);
- }
- }
-
- @Override
- public void onMainDestroy() {
- super.onMainDestroy();
- if (mPaymentManager != null) {
- mPaymentManager.destroy();
- }
- }
-
- public void purchase(final String sku, final String transactionId) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mPaymentManager.requestPurchase(sku, transactionId);
- }
- });
- }
-
- public void consumeUnconsumedPurchases() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mPaymentManager.consumeUnconsumedPurchases();
- }
- });
- }
-
- private String signature;
-
- public String getSignature() {
- return this.signature;
- }
-
- public void callbackSuccess(String ticket, String signature, String sku) {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[] { ticket, signature, sku });
- }
-
- public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku) {
- Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > " + ticket + "," + signature + "," + sku);
- GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[] { ticket, signature, sku });
- }
-
- public void callbackSuccessNoUnconsumedPurchases() {
- GodotLib.calldeferred(purchaseCallbackId, "consume_not_required", new Object[] {});
- }
-
- public void callbackFailConsume(String message) {
- GodotLib.calldeferred(purchaseCallbackId, "consume_fail", new Object[] { message });
- }
-
- public void callbackFail(String message) {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[] { message });
- }
-
- public void callbackCancel() {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[] {});
- }
-
- public void callbackAlreadyOwned(String sku) {
- GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[] { sku });
- }
-
- public long getPurchaseCallbackId() {
- return purchaseCallbackId;
- }
-
- public void setPurchaseCallbackId(long purchaseCallbackId) {
- this.purchaseCallbackId = purchaseCallbackId;
- }
-
- public String getPurchaseValidationUrlPrefix() {
- return this.purchaseValidationUrlPrefix;
- }
-
- public void setPurchaseValidationUrlPrefix(String url) {
- this.purchaseValidationUrlPrefix = url;
- }
-
- public String getAccessToken() {
- return accessToken;
- }
-
- public void setAccessToken(String accessToken) {
- this.accessToken = accessToken;
- }
-
- public void setTransactionId(String transactionId) {
- this.transactionId = transactionId;
- }
-
- public String getTransactionId() {
- return this.transactionId;
- }
-
- // request purchased items are not consumed
- public void requestPurchased() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mPaymentManager.requestPurchased();
- }
- });
- }
-
- // callback for requestPurchased()
- public void callbackPurchased(String receipt, String signature, String sku) {
- GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[] { receipt, signature, sku });
- }
-
- public void callbackDisconnected() {
- GodotLib.calldeferred(purchaseCallbackId, "iap_disconnected", new Object[] {});
- }
-
- public void callbackConnected() {
- GodotLib.calldeferred(purchaseCallbackId, "iap_connected", new Object[] {});
- }
-
- // true if connected, false otherwise
- public boolean isConnected() {
- return mPaymentManager.isConnected();
- }
-
- // consume item automatically after purchase. default is true.
- public void setAutoConsume(boolean autoConsume) {
- mPaymentManager.setAutoConsume(autoConsume);
- }
-
- // consume a specific item
- public void consume(String sku) {
- mPaymentManager.consume(sku);
- }
-
- // query in app item detail info
- public void querySkuDetails(String[] list) {
- List<String> nKeys = Arrays.asList(list);
- List<String> cKeys = Arrays.asList(mSkuDetails.get_keys());
- ArrayList<String> fKeys = new ArrayList<String>();
- for (String key : nKeys) {
- if (!cKeys.contains(key)) {
- fKeys.add(key);
- }
- }
- if (fKeys.size() > 0) {
- mPaymentManager.querySkuDetails(fKeys.toArray(new String[0]));
- } else {
- completeSkuDetail();
- }
- }
-
- public void addSkuDetail(String itemJson) {
- JSONObject o = null;
- try {
- o = new JSONObject(itemJson);
- Dictionary item = new Dictionary();
- item.put("type", o.optString("type"));
- item.put("product_id", o.optString("productId"));
- item.put("title", o.optString("title"));
- item.put("description", o.optString("description"));
- item.put("price", o.optString("price"));
- item.put("price_currency_code", o.optString("price_currency_code"));
- item.put("price_amount", 0.000001d * o.optLong("price_amount_micros"));
- mSkuDetails.put(item.get("product_id").toString(), item);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
-
- public void completeSkuDetail() {
- GodotLib.calldeferred(purchaseCallbackId, "sku_details_complete", new Object[] { mSkuDetails });
- }
-
- public void errorSkuDetail(String errorMessage) {
- GodotLib.calldeferred(purchaseCallbackId, "sku_details_error", new Object[] { errorMessage });
- }
-
- @NonNull
- @Override
- public String getPluginName() {
- return "GodotPayment";
- }
-
- @NonNull
- @Override
- public List<String> getPluginMethods() {
- return Arrays.asList("purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix",
- "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased",
- "setAutoConsume", "consume", "querySkuDetails", "isConnected");
- }
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/HandlePurchaseTask.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/HandlePurchaseTask.java
deleted file mode 100644
index 00e216e8c0..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/HandlePurchaseTask.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*************************************************************************/
-/* HandlePurchaseTask.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import android.app.Activity;
-import android.content.Intent;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-abstract public class HandlePurchaseTask {
- private Activity context;
-
- public HandlePurchaseTask(Activity context) {
- this.context = context;
- }
-
- public void handlePurchaseRequest(int resultCode, Intent data) {
- //Log.d("XXX", "Handling purchase response");
- if (resultCode == Activity.RESULT_OK) {
- try {
- //int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
- PaymentsCache pc = new PaymentsCache(context);
-
- String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
- //Log.d("XXX", "Purchase data:" + purchaseData);
- String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
- //Log.d("XXX", "Purchase signature:" + dataSignature);
- //Log.d("SARLANGA", purchaseData);
-
- JSONObject jo = new JSONObject(purchaseData);
- //String sku = jo.getString("productId");
- //alert("You have bought the " + sku + ". Excellent choice, aventurer!");
- //String orderId = jo.getString("orderId");
- //String packageName = jo.getString("packageName");
- String productId = jo.getString("productId");
- //Long purchaseTime = jo.getLong("purchaseTime");
- //Integer state = jo.getInt("purchaseState");
- String developerPayload = jo.getString("developerPayload");
- String purchaseToken = jo.getString("purchaseToken");
-
- if (!pc.getConsumableValue("validation_hash", productId).equals(developerPayload)) {
- error("Untrusted callback");
- return;
- }
- //Log.d("XXX", "Este es el product ID:" + productId);
- pc.setConsumableValue("ticket_signautre", productId, dataSignature);
- pc.setConsumableValue("ticket", productId, purchaseData);
- pc.setConsumableFlag("block", productId, true);
- pc.setConsumableValue("token", productId, purchaseToken);
-
- success(productId, dataSignature, purchaseData);
- return;
- } catch (JSONException e) {
- error(e.getMessage());
- }
- } else if (resultCode == Activity.RESULT_CANCELED) {
- canceled();
- }
- }
-
- abstract protected void success(String sku, String signature, String ticket);
- abstract protected void error(String message);
- abstract protected void canceled();
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsCache.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsCache.java
deleted file mode 100644
index 435f43c49d..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsCache.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*************************************************************************/
-/* PaymentsCache.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-public class PaymentsCache {
- public Context context;
-
- public PaymentsCache(Context context) {
- this.context = context;
- }
-
- public void setConsumableFlag(String set, String sku, Boolean flag) {
- SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putBoolean(sku, flag);
- editor.apply();
- }
-
- public boolean getConsumableFlag(String set, String sku) {
- SharedPreferences sharedPref = context.getSharedPreferences(
- "consumables_" + set, Context.MODE_PRIVATE);
- return sharedPref.getBoolean(sku, false);
- }
-
- public void setConsumableValue(String set, String sku, String value) {
- SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString(sku, value);
- //Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
- editor.apply();
- }
-
- public String getConsumableValue(String set, String sku) {
- SharedPreferences sharedPref = context.getSharedPreferences(
- "consumables_" + set, Context.MODE_PRIVATE);
- //Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
- return sharedPref.getString(sku, null);
- }
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsManager.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsManager.java
deleted file mode 100644
index 9b3a338866..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PaymentsManager.java
+++ /dev/null
@@ -1,403 +0,0 @@
-/*************************************************************************/
-/* PaymentsManager.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.vending.billing.IInAppBillingService;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class PaymentsManager {
- public static final int BILLING_RESPONSE_RESULT_OK = 0;
- public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
- private static boolean auto_consume = true;
-
- private final Activity activity;
- private final GodotPayment godotPayment;
- IInAppBillingService mService;
-
- PaymentsManager(Activity activity, GodotPayment godotPayment) {
- this.activity = activity;
- this.godotPayment = godotPayment;
- }
-
- public PaymentsManager initService() {
- Intent intent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
- intent.setPackage("com.android.vending");
- activity.bindService(
- intent,
- mServiceConn,
- Context.BIND_AUTO_CREATE);
- return this;
- }
-
- public void destroy() {
- if (mService != null) {
- activity.unbindService(mServiceConn);
- }
- }
-
- ServiceConnection mServiceConn = new ServiceConnection() {
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mService = null;
-
- // At this stage, godotPayment might not have been initialized yet.
- if (godotPayment != null) {
- godotPayment.callbackDisconnected();
- }
- }
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mService = IInAppBillingService.Stub.asInterface(service);
-
- // At this stage, godotPayment might not have been initialized yet.
- if (godotPayment != null) {
- godotPayment.callbackConnected();
- }
- }
- };
-
- public void requestPurchase(final String sku, String transactionId) {
- new PurchaseTask(mService, activity) {
- @Override
- protected void error(String message) {
- godotPayment.callbackFail(message);
- }
-
- @Override
- protected void canceled() {
- godotPayment.callbackCancel();
- }
-
- @Override
- protected void alreadyOwned() {
- godotPayment.callbackAlreadyOwned(sku);
- }
- }
- .purchase(sku, transactionId);
- }
-
- public boolean isConnected() {
- return mService != null;
- }
-
- public void consumeUnconsumedPurchases() {
- new ReleaseAllConsumablesTask(mService, activity) {
- @Override
- protected void success(String sku, String receipt, String signature, String token) {
- godotPayment.callbackSuccessProductMassConsumed(receipt, signature, sku);
- }
-
- @Override
- protected void error(String message) {
- Log.d("godot", "consumeUnconsumedPurchases :" + message);
- godotPayment.callbackFailConsume(message);
- }
-
- @Override
- protected void notRequired() {
- Log.d("godot", "callbackSuccessNoUnconsumedPurchases :");
- godotPayment.callbackSuccessNoUnconsumedPurchases();
- }
- }
- .consumeItAll();
- }
-
- public void requestPurchased() {
- try {
- PaymentsCache pc = new PaymentsCache(activity);
-
- String continueToken = null;
-
- do {
- Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp", continueToken);
-
- if (bundle.getInt("RESPONSE_CODE") == 0) {
- final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
- final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
-
- if (myPurchases == null || myPurchases.size() == 0) {
- godotPayment.callbackPurchased("", "", "");
- return;
- }
-
- for (int i = 0; i < myPurchases.size(); i++) {
- try {
- String receipt = myPurchases.get(i);
- JSONObject inappPurchaseData = new JSONObject(receipt);
- String sku = inappPurchaseData.getString("productId");
- String token = inappPurchaseData.getString("purchaseToken");
- String signature = mySignatures.get(i);
-
- pc.setConsumableValue("ticket_signautre", sku, signature);
- pc.setConsumableValue("ticket", sku, receipt);
- pc.setConsumableFlag("block", sku, true);
- pc.setConsumableValue("token", sku, token);
-
- godotPayment.callbackPurchased(receipt, signature, sku);
- } catch (JSONException e) {
- }
- }
- }
- continueToken = bundle.getString("INAPP_CONTINUATION_TOKEN");
- Log.d("godot", "continue token = " + continueToken);
- } while (!TextUtils.isEmpty(continueToken));
- } catch (Exception e) {
- Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage());
- }
- }
-
- public void processPurchaseResponse(int resultCode, Intent data) {
- new HandlePurchaseTask(activity) {
- @Override
- protected void success(final String sku, final String signature, final String ticket) {
- godotPayment.callbackSuccess(ticket, signature, sku);
-
- if (auto_consume) {
- new ConsumeTask(mService, activity) {
- @Override
- protected void success(String ticket) {
- }
-
- @Override
- protected void error(String message) {
- godotPayment.callbackFail(message);
- }
- }
- .consume(sku);
- }
- }
-
- @Override
- protected void error(String message) {
- godotPayment.callbackFail(message);
- }
-
- @Override
- protected void canceled() {
- godotPayment.callbackCancel();
- }
- }
- .handlePurchaseRequest(resultCode, data);
- }
-
- public void validatePurchase(String purchaseToken, final String sku) {
- new ValidateTask(activity, godotPayment) {
- @Override
- protected void success() {
- new ConsumeTask(mService, activity) {
- @Override
- protected void success(String ticket) {
- godotPayment.callbackSuccess(ticket, null, sku);
- }
-
- @Override
- protected void error(String message) {
- godotPayment.callbackFail(message);
- }
- }
- .consume(sku);
- }
-
- @Override
- protected void error(String message) {
- godotPayment.callbackFail(message);
- }
-
- @Override
- protected void canceled() {
- godotPayment.callbackCancel();
- }
- }
- .validatePurchase(sku);
- }
-
- public void setAutoConsume(boolean autoConsume) {
- auto_consume = autoConsume;
- }
-
- public void consume(final String sku) {
- new ConsumeTask(mService, activity) {
- @Override
- protected void success(String ticket) {
- godotPayment.callbackSuccessProductMassConsumed(ticket, "", sku);
- }
-
- @Override
- protected void error(String message) {
- godotPayment.callbackFailConsume(message);
- }
- }
- .consume(sku);
- }
-
- // Workaround to bug where sometimes response codes come as Long instead of Integer
- int getResponseCodeFromBundle(Bundle b) {
- Object o = b.get("RESPONSE_CODE");
- if (o == null) {
- //logDebug("Bundle with null response code, assuming OK (known issue)");
- return BILLING_RESPONSE_RESULT_OK;
- } else if (o instanceof Integer)
- return ((Integer)o).intValue();
- else if (o instanceof Long)
- return (int)((Long)o).longValue();
- else {
- //logError("Unexpected type for bundle response code.");
- //logError(o.getClass().getName());
- throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName());
- }
- }
-
- /**
- * Returns a human-readable description for the given response code.
- *
- * @param code The response code
- * @return A human-readable string explaining the result code.
- * It also includes the result code numerically.
- */
- public static String getResponseDesc(int code) {
- String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/"
- +
- "3:Billing Unavailable/4:Item unavailable/"
- +
- "5:Developer Error/6:Error/7:Item Already Owned/"
- +
- "8:Item not owned")
- .split("/");
- String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/"
- +
- "-1002:Bad response received/"
- +
- "-1003:Purchase signature verification failed/"
- +
- "-1004:Send intent failed/"
- +
- "-1005:User cancelled/"
- +
- "-1006:Unknown purchase response/"
- +
- "-1007:Missing token/"
- +
- "-1008:Unknown error/"
- +
- "-1009:Subscriptions not available/"
- +
- "-1010:Invalid consumption attempt")
- .split("/");
-
- if (code <= -1000) {
- int index = -1000 - code;
- if (index >= 0 && index < iabhelper_msgs.length)
- return iabhelper_msgs[index];
- else
- return String.valueOf(code) + ":Unknown IAB Helper Error";
- } else if (code < 0 || code >= iab_msgs.length)
- return String.valueOf(code) + ":Unknown";
- else
- return iab_msgs[code];
- }
-
- public void querySkuDetails(final String[] list) {
- (new Thread(new Runnable() {
- @Override
- public void run() {
- ArrayList<String> skuList = new ArrayList<String>(Arrays.asList(list));
- if (skuList.size() == 0) {
- return;
- }
- // Split the sku list in blocks of no more than 20 elements.
- ArrayList<ArrayList<String>> packs = new ArrayList<ArrayList<String>>();
- ArrayList<String> tempList;
- int n = skuList.size() / 20;
- int mod = skuList.size() % 20;
- for (int i = 0; i < n; i++) {
- tempList = new ArrayList<String>();
- for (String s : skuList.subList(i * 20, i * 20 + 20)) {
- tempList.add(s);
- }
- packs.add(tempList);
- }
- if (mod != 0) {
- tempList = new ArrayList<String>();
- for (String s : skuList.subList(n * 20, n * 20 + mod)) {
- tempList.add(s);
- }
- packs.add(tempList);
- }
- for (ArrayList<String> skuPartList : packs) {
- Bundle querySkus = new Bundle();
- querySkus.putStringArrayList("ITEM_ID_LIST", skuPartList);
- Bundle skuDetails = null;
- try {
- skuDetails = mService.getSkuDetails(3, activity.getPackageName(), "inapp", querySkus);
- if (!skuDetails.containsKey("DETAILS_LIST")) {
- int response = getResponseCodeFromBundle(skuDetails);
- if (response != BILLING_RESPONSE_RESULT_OK) {
- godotPayment.errorSkuDetail(getResponseDesc(response));
- } else {
- godotPayment.errorSkuDetail("No error but no detail list.");
- }
- return;
- }
-
- ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
-
- for (String thisResponse : responseList) {
- Log.d("godot", "response = " + thisResponse);
- godotPayment.addSkuDetail(thisResponse);
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- godotPayment.errorSkuDetail("RemoteException error!");
- }
- }
- godotPayment.completeSkuDetail();
- }
- }))
- .start();
- }
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java
deleted file mode 100644
index f894bd5132..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*************************************************************************/
-/* PurchaseTask.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.content.IntentSender.SendIntentException;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.vending.billing.IInAppBillingService;
-
-abstract public class PurchaseTask {
- private Activity context;
-
- private IInAppBillingService mService;
- public PurchaseTask(IInAppBillingService mService, Activity context) {
- this.context = context;
- this.mService = mService;
- }
-
- private boolean isLooping = false;
-
- public void purchase(final String sku, final String transactionId) {
- Log.d("XXX", "Starting purchase for: " + sku);
- PaymentsCache pc = new PaymentsCache(context);
- Boolean isBlocked = pc.getConsumableFlag("block", sku);
- /*
- if(isBlocked) {
- Log.d("XXX", "Is awaiting payment confirmation");
- error("Awaiting payment confirmation");
- return;
- }
- */
- final String hash = transactionId;
-
- Bundle buyIntentBundle;
- try {
- buyIntentBundle = mService.getBuyIntent(3, context.getApplicationContext().getPackageName(), sku, "inapp", hash);
- } catch (RemoteException e) {
- //Log.d("XXX", "Error: " + e.getMessage());
- error(e.getMessage());
- return;
- }
- Object rc = buyIntentBundle.get("RESPONSE_CODE");
- int responseCode = 0;
- if (rc == null) {
- responseCode = PaymentsManager.BILLING_RESPONSE_RESULT_OK;
- } else if (rc instanceof Integer) {
- responseCode = ((Integer)rc).intValue();
- } else if (rc instanceof Long) {
- responseCode = (int)((Long)rc).longValue();
- }
- //Log.d("XXX", "Buy intent response code: " + responseCode);
- if (responseCode == 1 || responseCode == 3 || responseCode == 4) {
- canceled();
- return;
- }
- if (responseCode == 7) {
- alreadyOwned();
- return;
- }
-
- PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
- pc.setConsumableValue("validation_hash", sku, hash);
- try {
- if (context == null) {
- //Log.d("XXX", "No context!");
- }
- if (pendingIntent == null) {
- //Log.d("XXX", "No pending intent");
- }
- //Log.d("XXX", "Starting activity for purchase!");
- context.startIntentSenderForResult(
- pendingIntent.getIntentSender(),
- PaymentsManager.REQUEST_CODE_FOR_PURCHASE,
- new Intent(),
- Integer.valueOf(0), Integer.valueOf(0),
- Integer.valueOf(0));
- } catch (SendIntentException e) {
- error(e.getMessage());
- }
- }
-
- abstract protected void error(String message);
- abstract protected void canceled();
- abstract protected void alreadyOwned();
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ReleaseAllConsumablesTask.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ReleaseAllConsumablesTask.java
deleted file mode 100644
index 1d52cf0fa5..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ReleaseAllConsumablesTask.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*************************************************************************/
-/* ReleaseAllConsumablesTask.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.vending.billing.IInAppBillingService;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-abstract public class ReleaseAllConsumablesTask {
- private Context context;
- private IInAppBillingService mService;
-
- private static class ReleaseAllConsumablesAsyncTask extends AsyncTask<String, String, String> {
- private WeakReference<ReleaseAllConsumablesTask> mTask;
- private String mSku;
- private String mReceipt;
- private String mSignature;
- private String mToken;
-
- ReleaseAllConsumablesAsyncTask(ReleaseAllConsumablesTask task, String sku, String receipt, String signature, String token) {
- mTask = new WeakReference<ReleaseAllConsumablesTask>(task);
-
- mSku = sku;
- mReceipt = receipt;
- mSignature = signature;
- mToken = token;
- }
-
- @Override
- protected String doInBackground(String... params) {
- ReleaseAllConsumablesTask consume = mTask.get();
- if (consume != null) {
- return consume.doInBackground(mToken);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(String param) {
- ReleaseAllConsumablesTask consume = mTask.get();
- if (consume != null) {
- consume.success(mSku, mReceipt, mSignature, mToken);
- }
- }
- }
-
- public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context) {
- this.context = context;
- this.mService = mService;
- }
-
- public void consumeItAll() {
- try {
- //Log.d("godot", "consumeItall for " + context.getPackageName());
- Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp", null);
-
- if (bundle.getInt("RESPONSE_CODE") == 0) {
- final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
- final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
-
- if (myPurchases == null || myPurchases.size() == 0) {
- //Log.d("godot", "No purchases!");
- notRequired();
- return;
- }
-
- //Log.d("godot", "# products to be consumed:" + myPurchases.size());
- for (int i = 0; i < myPurchases.size(); i++) {
- try {
- String receipt = myPurchases.get(i);
- JSONObject inappPurchaseData = new JSONObject(receipt);
- String sku = inappPurchaseData.getString("productId");
- String token = inappPurchaseData.getString("purchaseToken");
- String signature = mySignatures.get(i);
- //Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
- new ReleaseAllConsumablesAsyncTask(this, sku, receipt, signature, token).execute();
- } catch (JSONException e) {
- }
- }
- }
- } catch (Exception e) {
- Log.d("godot", "Error releasing products:" + e.getClass().getName() + ":" + e.getMessage());
- }
- }
-
- private String doInBackground(String token) {
- try {
- //Log.d("godot", "Requesting to consume an item with token ." + token);
- int response = mService.consumePurchase(3, context.getPackageName(), token);
- //Log.d("godot", "consumePurchase response: " + response);
- if (response == 0 || response == 8) {
- return null;
- }
- } catch (Exception e) {
- Log.d("godot", "Error " + e.getClass().getName() + ":" + e.getMessage());
- }
- return null;
- }
-
- abstract protected void success(String sku, String receipt, String signature, String token);
- abstract protected void error(String message);
- abstract protected void notRequired();
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ValidateTask.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ValidateTask.java
deleted file mode 100644
index a7156152ce..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/ValidateTask.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*************************************************************************/
-/* ValidateTask.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment;
-
-import org.godotengine.godot.plugin.payment.utils.HttpRequester;
-import org.godotengine.godot.plugin.payment.utils.RequestParams;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.os.AsyncTask;
-
-import java.lang.ref.WeakReference;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-abstract public class ValidateTask {
- private Activity context;
- private GodotPayment godotPayments;
- private ProgressDialog dialog;
- private String mSku;
-
- private static class ValidateAsyncTask extends AsyncTask<String, String, String> {
- private WeakReference<ValidateTask> mTask;
-
- ValidateAsyncTask(ValidateTask task) {
- mTask = new WeakReference<>(task);
- }
-
- @Override
- protected void onPreExecute() {
- ValidateTask task = mTask.get();
- if (task != null) {
- task.onPreExecute();
- }
- }
-
- @Override
- protected String doInBackground(String... params) {
- ValidateTask task = mTask.get();
- if (task != null) {
- return task.doInBackground(params);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(String response) {
- ValidateTask task = mTask.get();
- if (task != null) {
- task.onPostExecute(response);
- }
- }
- }
-
- public ValidateTask(Activity context, GodotPayment godotPayments) {
- this.context = context;
- this.godotPayments = godotPayments;
- }
-
- public void validatePurchase(final String sku) {
- mSku = sku;
- new ValidateAsyncTask(this).execute();
- }
-
- private void onPreExecute() {
- dialog = ProgressDialog.show(context, null, "Please wait...");
- }
-
- private String doInBackground(String... params) {
- PaymentsCache pc = new PaymentsCache(context);
- String url = godotPayments.getPurchaseValidationUrlPrefix();
- RequestParams param = new RequestParams();
- param.setUrl(url);
- param.put("ticket", pc.getConsumableValue("ticket", mSku));
- param.put("purchaseToken", pc.getConsumableValue("token", mSku));
- param.put("sku", mSku);
- //Log.d("XXX", "Haciendo request a " + url);
- //Log.d("XXX", "ticket: " + pc.getConsumableValue("ticket", sku));
- //Log.d("XXX", "purchaseToken: " + pc.getConsumableValue("token", sku));
- //Log.d("XXX", "sku: " + sku);
- param.put("package", context.getApplicationContext().getPackageName());
- HttpRequester requester = new HttpRequester();
- String jsonResponse = requester.post(param);
- //Log.d("XXX", "Validation response:\n"+jsonResponse);
- return jsonResponse;
- }
-
- private void onPostExecute(String response) {
- if (dialog != null) {
- dialog.dismiss();
- dialog = null;
- }
- JSONObject j;
- try {
- j = new JSONObject(response);
- if (j.getString("status").equals("OK")) {
- success();
- return;
- } else if (j.getString("status") != null) {
- error(j.getString("message"));
- } else {
- error("Connection error");
- }
- } catch (JSONException e) {
- error(e.getMessage());
- } catch (Exception e) {
- error(e.getMessage());
- }
- }
-
- abstract protected void success();
- abstract protected void error(String message);
- abstract protected void canceled();
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/HttpRequester.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/HttpRequester.java
deleted file mode 100644
index 0afcf60f38..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/HttpRequester.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*************************************************************************/
-/* HttpRequester.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment.utils;
-
-import org.godotengine.godot.utils.Crypt;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.security.KeyStore;
-import java.util.Date;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpVersion;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.util.EntityUtils;
-
-/**
- *
- * @author Luis Linietsky <luis.linietsky@gmail.com>
- */
-public class HttpRequester {
- private Context context;
- private static final int TTL = 600000; // 10 minutos
- private long cttl = 0;
-
- public HttpRequester() {
- //Log.d("XXX", "Creando http request sin contexto");
- }
-
- public HttpRequester(Context context) {
- this.context = context;
- //Log.d("XXX", "Creando http request con contexto");
- }
-
- public String post(RequestParams params) {
- HttpPost httppost = new HttpPost(params.getUrl());
- try {
- httppost.setEntity(new UrlEncodedFormEntity(params.toPairsList()));
- return request(httppost);
- } catch (UnsupportedEncodingException e) {
- return null;
- }
- }
-
- public String get(RequestParams params) {
- String response = getResponseFromCache(params.getUrl());
- if (response == null) {
- //Log.d("XXX", "Cache miss!");
- HttpGet httpget = new HttpGet(params.getUrl());
- long timeInit = new Date().getTime();
- response = request(httpget);
- long delay = new Date().getTime() - timeInit;
- Log.d("HttpRequest::get(url)", "Url: " + params.getUrl() + " downloaded in " + String.format("%.03f", delay / 1000.0f) + " seconds");
- if (response == null || response.length() == 0) {
- response = "";
- } else {
- saveResponseIntoCache(params.getUrl(), response);
- }
- }
- Log.d("XXX", "Req: " + params.getUrl());
- Log.d("XXX", "Resp: " + response);
- return response;
- }
-
- private String request(HttpUriRequest request) {
- //Log.d("XXX", "Haciendo request a: " + request.getURI() );
- Log.d("PPP", "Haciendo request a: " + request.getURI());
- long init = new Date().getTime();
- HttpClient httpclient = getNewHttpClient();
- HttpParams httpParameters = httpclient.getParams();
- HttpConnectionParams.setConnectionTimeout(httpParameters, 0);
- HttpConnectionParams.setSoTimeout(httpParameters, 0);
- HttpConnectionParams.setTcpNoDelay(httpParameters, true);
- try {
- HttpResponse response = httpclient.execute(request);
- Log.d("PPP", "Fin de request (" + (new Date().getTime() - init) + ") a: " + request.getURI());
- //Log.d("XXX1", "Status:" + response.getStatusLine().toString());
- if (response.getStatusLine().getStatusCode() == 200) {
- String strResponse = EntityUtils.toString(response.getEntity());
- //Log.d("XXX2", strResponse);
- return strResponse;
- } else {
- Log.d("XXX3", "Response status code:" + response.getStatusLine().getStatusCode() + "\n" + EntityUtils.toString(response.getEntity()));
- return null;
- }
-
- } catch (ClientProtocolException e) {
- Log.d("XXX3", e.getMessage());
- } catch (IOException e) {
- Log.d("XXX4", e.getMessage());
- }
- return null;
- }
-
- private HttpClient getNewHttpClient() {
- try {
- KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
- trustStore.load(null, null);
-
- SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
- sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
-
- HttpParams params = new BasicHttpParams();
- HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
- HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
-
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", sf, 443));
-
- ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
-
- return new DefaultHttpClient(ccm, params);
- } catch (Exception e) {
- return new DefaultHttpClient();
- }
- }
-
- private static String convertStreamToString(InputStream is) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(is));
- StringBuilder sb = new StringBuilder();
- String line = null;
- try {
- while ((line = reader.readLine()) != null) {
- sb.append((line + "\n"));
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return sb.toString();
- }
-
- public void saveResponseIntoCache(String request, String response) {
- if (context == null) {
- //Log.d("XXX", "No context, cache failed!");
- return;
- }
- SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.putString("request_" + Crypt.md5(request), response);
- editor.putLong("request_" + Crypt.md5(request) + "_ttl", new Date().getTime() + getTtl());
- editor.apply();
- }
-
- public String getResponseFromCache(String request) {
- if (context == null) {
- Log.d("XXX", "No context, cache miss");
- return null;
- }
- SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
- long ttl = getResponseTtl(request);
- if (ttl == 0l || (new Date().getTime() - ttl) > 0l) {
- Log.d("XXX", "Cache invalid ttl:" + ttl + " vs now:" + new Date().getTime());
- return null;
- }
- return sharedPref.getString("request_" + Crypt.md5(request), null);
- }
-
- public long getResponseTtl(String request) {
- SharedPreferences sharedPref = context.getSharedPreferences(
- "http_get_cache", Context.MODE_PRIVATE);
- return sharedPref.getLong("request_" + Crypt.md5(request) + "_ttl", 0l);
- }
-
- public long getTtl() {
- return cttl > 0 ? cttl : TTL;
- }
-
- public void setTtl(long ttl) {
- this.cttl = (ttl * 1000) + new Date().getTime();
- }
-}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/RequestParams.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/RequestParams.java
deleted file mode 100644
index 6b66c7e474..0000000000
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/RequestParams.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************/
-/* RequestParams.java */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-package org.godotengine.godot.plugin.payment.utils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import org.apache.http.NameValuePair;
-import org.apache.http.message.BasicNameValuePair;
-
-/**
- *
- * @author Luis Linietsky <luis.linietsky@gmail.com>
- */
-public class RequestParams {
- private HashMap<String, String> params;
- private String url;
-
- public RequestParams() {
- params = new HashMap<String, String>();
- }
-
- public void put(String key, String value) {
- params.put(key, value);
- }
-
- public String get(String key) {
- return params.get(key);
- }
-
- public void remove(Object key) {
- params.remove(key);
- }
-
- public boolean has(String key) {
- return params.containsKey(key);
- }
-
- public List<NameValuePair> toPairsList() {
- List<NameValuePair> fields = new ArrayList<NameValuePair>();
-
- for (String key : params.keySet()) {
- fields.add(new BasicNameValuePair(key, this.get(key)));
- }
- return fields;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-}
diff --git a/platform/android/java/settings.gradle b/platform/android/java/settings.gradle
index 9536d3de6d..524031d93f 100644
--- a/platform/android/java/settings.gradle
+++ b/platform/android/java/settings.gradle
@@ -3,4 +3,4 @@ rootProject.name = "Godot"
include ':app'
include ':lib'
-include ':plugins:godotpayment'
+include ':nativeSrcsConfigs'