From ae2afee14ce6c3b4cd3eb17ef633cb9c3ea10096 Mon Sep 17 00:00:00 2001 From: Steve Hannah Date: Sat, 9 Sep 2023 10:01:09 -0700 Subject: [PATCH] Feature/facebook sdk 16 (#3731) * Removed AppInvite dialog code for migration to Facebook SDK 16.2.0 * Added support for Facebook SDK 16 in android gradle version. Still WIP. For build to successed, it seams that gradle version >= 7.2 is required, which requires JDK 11. But since we already needto update to gradle 8.1 for firebase support, we may want to simply skip that, and do what is required to get gradle 8.1 working as the new standard. * Updated facebook and FCM support. Both of these require gradle 8.1, which requires JDK 17, but builder still doesn't support JDK17 in general, so for android builds we need to set JAVA17_HOME environment variable when performing Android local builds. * isFriendsInviteSupported now returns false for facebook --- .../com/codename1/social/FacebookImpl.java | 68 +--- .../builders/AndroidGradleBuilder.java | 325 ++++++++++++++---- 2 files changed, 252 insertions(+), 141 deletions(-) diff --git a/Ports/Android/src/com/codename1/social/FacebookImpl.java b/Ports/Android/src/com/codename1/social/FacebookImpl.java index 3b528df811..e59f241e10 100644 --- a/Ports/Android/src/com/codename1/social/FacebookImpl.java +++ b/Ports/Android/src/com/codename1/social/FacebookImpl.java @@ -34,8 +34,6 @@ import com.facebook.FacebookException; import com.facebook.FacebookSdk; import com.facebook.login.LoginManager; -import com.facebook.share.model.AppInviteContent; -import com.facebook.share.widget.AppInviteDialog; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -71,10 +69,7 @@ public static void init() { } catch (Exception e) { //the pattern is not valid } - } - FacebookSdk.sdkInitialize(AndroidNativeUtil.getContext().getApplicationContext()); - } @Override @@ -200,71 +195,12 @@ public void inviteFriends(String appLinkUrl, String previewImageUrl) { @Override public void inviteFriends(String appLinkUrl, String previewImageUrl, final Callback cb) { - if (AndroidNativeUtil.getActivity() == null) { - throw new RuntimeException("Cannot invite friends while running in the background."); - } - if (AppInviteDialog.canShow()) { - AppInviteContent content = new AppInviteContent.Builder() - .setApplinkUrl(appLinkUrl) - .setPreviewImageUrl(previewImageUrl) - .build(); - final CodenameOneActivity activity = (CodenameOneActivity) AndroidNativeUtil.getActivity(); - if(cb == null){ - AppInviteDialog.show(activity, content); - }else{ - AppInviteDialog appInviteDialog = new AppInviteDialog(activity); - final CallbackManager mCallbackManager = CallbackManager.Factory.create(); - activity.setIntentResultListener(new IntentResultListener() { - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - mCallbackManager.onActivityResult(requestCode, resultCode, data); - activity.restoreIntentResultListener(); - } - }); - appInviteDialog.registerCallback(mCallbackManager, new FacebookCallback() { - @Override - public void onSuccess(AppInviteDialog.Result result) { - Display.getInstance().callSerially(new Runnable() { - - @Override - public void run() { - cb.onSucess(null); - } - }); - } - - @Override - public void onCancel() { - Display.getInstance().callSerially(new Runnable() { - - @Override - public void run() { - cb.onError(null, null, -1, "User Cancelled"); - } - }); - } - - @Override - public void onError(final FacebookException e) { - Display.getInstance().callSerially(new Runnable() { - - @Override - public void run() { - cb.onError(null, e, 0, e.getMessage()); - } - }); - } - }); - appInviteDialog.show(content); - } - } - + throw new RuntimeException("The Facebook App Invite feature is no longer supported by the Facebook SDK. See https://developers.facebook.com/blog/post/2017/11/07/changes-developer-offerings/"); } @Override public boolean isInviteFriendsSupported() { - return true; + return false; } class FBCallback implements FacebookCallback { diff --git a/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java b/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java index 1b5bb7d1e1..4d798a1d2f 100644 --- a/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java +++ b/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java @@ -76,20 +76,35 @@ * @author Steve Hannah */ public class AndroidGradleBuilder extends Executor { - private static final float MIN_GRADLE_VERSION=6; - private static final String gradleDistributionUrl = "https://services.gradle.org/distributions/gradle-6.8.3-bin.zip"; - public static final boolean PREFER_MANAGED_GRADLE=true; + + private float MIN_GRADLE_VERSION=6; + + private float MIN_JDK_VERSION=8; + + private String gradleDistributionUrl = "https://services.gradle.org/distributions/gradle-6.8.3-bin.zip"; + + private String gradle8DistributionUrl = "https://services.gradle.org/distributions/gradle-8.1-bin.zip"; + public boolean PREFER_MANAGED_GRADLE=true; + + private boolean useGradle8 = true; + private boolean useJava8SourceLevel = true; private File gradleProjectDirectory; private boolean playServicesVersionSetInBuildHint = false; + private String facebookSdkVersion; + public File getGradleProjectDirectory() { return gradleProjectDirectory; } private boolean decouplePlayServiceVersions = false; + // Temporary flag to update firebase messaging to version 23.2.1 + // which is necessary to support Push on the latest Android devices. + private boolean newFirebaseMessaging = false; + public static final String[] ANDROID_PERMISSIONS = new String[]{ "android.permission.ACCESS_BACKGROUND_LOCATION", "android.permission.ACCESS_CHECKIN_PROPERTIES", @@ -391,7 +406,7 @@ protected long getTimeoutValue() { private String getGradleVersion(String gradleExe) throws Exception { Map env = defaultEnvironment; - env.put("JAVA_HOME", System.getProperty("java.home")); + env.put("JAVA_HOME", getGradleJavaHome()); String result = execString(new File(System.getProperty("user.dir")), gradleExe, "--version"); Scanner scanner = new Scanner(result); @@ -405,6 +420,22 @@ private String getGradleVersion(String gradleExe) throws Exception { throw new RuntimeException("Failed to get gradle version for "+gradleExe); } + private String getGradleJavaHome() throws BuildException { + if (useGradle8) { + String home = System.getenv("JAVA17_HOME"); + if (home == null) { + throw new BuildException("When using gradle 8, you must set the JAVA17_HOME environment variable to the location of a Java 17 JDK"); + } + + if (!(new File(home).isDirectory())) { + throw new BuildException("The JAVA17_HOME environment variable is not set to a valid directory"); + } + + return home; + } + return System.getProperty("java.home"); + } + private int parseVersionStringAsInt(String versionString) { if (versionString.indexOf(".") > 0) { try { @@ -434,6 +465,22 @@ private static String escape(String str, String chars) { @Override public boolean build(File sourceZip, final BuildRequest request) throws BuildException { + boolean facebookSupported = request.getArg("facebook.appId", null) != null; + newFirebaseMessaging = request.getArg("android.newFirebaseMessaging", "false").equals("true"); + useGradle8 = request.getArg("android.useGradle8", ""+(useGradle8 || newFirebaseMessaging || facebookSupported)).equals("true"); + useJava8SourceLevel = request.getArg("android.java8", ""+useJava8SourceLevel).equals("true"); + if (useGradle8) { + getGradleJavaHome(); // will throw build exception if JAVA17_HOME is not set + MIN_GRADLE_VERSION = 8; + gradleDistributionUrl = gradle8DistributionUrl; + if (!useJava8SourceLevel) { + log("NOTICE: Enabling Java 8 source level for Gradle 8 build because RetroLambda is not supported on Java 17, which is required for gradle 8."); + useJava8SourceLevel = true; + } + } + if (newFirebaseMessaging && !useGradle8) { + throw new BuildException("android.newFirebaseMessaging requires gradle version 8.1 or higher. Please remove the android.gradleVersion build hint"); + } debug("Request Args: "); debug("-----------------"); for (String arg : request.getArgs()) { @@ -441,7 +488,26 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc } debug("-------------------"); - decouplePlayServiceVersions = request.getArg("android.decouplePlayServiceVersions", "false").equals("true"); + facebookSdkVersion = request.getArg("android.facebookSdkVersion", "16.2.0"); + String facebookSupport = ""; + String facebookProguard = ""; + String facebookActivityMetaData = ""; + String facebookActivity = ""; + String facebookHashCode = ""; + String facebookClientToken = null; + + if (facebookSupported && compareVersions(facebookSdkVersion, "16.0.0") >= 0) { + facebookClientToken = request.getArg("facebook.clientToken", null); + if (facebookClientToken == null) { + throw new BuildException("You must specify a facebook.clientToken when using facebookSdkVersion "+facebookSdkVersion); + } + } + decouplePlayServiceVersions = request.getArg("android.decouplePlayServiceVersions", newFirebaseMessaging ? "true" : "false").equals("true"); + if (!decouplePlayServiceVersions && newFirebaseMessaging) { + throw new BuildException( + "android.newFirebaseMessaging=true is not compatible with android.decouplePlayServiceVersions=false. Please remove one of these build hints." + ); + } String defaultAndroidHome = isMac ? path(System.getProperty("user.home"), "Library", "Android", "sdk") : is_windows ? path(System.getProperty("user.home"), "AppData", "Local", "Android", "sdk") @@ -544,18 +610,39 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc maxBuildToolsVersion = "31"; } + if (useGradle8) { + maxBuildToolsVersionInt = Math.max(33, maxBuildToolsVersionInt); + maxBuildToolsVersion = "" + maxBuildToolsVersionInt; + maxPlatformVersionInt = Math.max(33, maxPlatformVersionInt); + maxPlatformVersion = "" + maxPlatformVersionInt; + } - useAndroidX = request.getArg("android.useAndroidX", decouplePlayServiceVersions ? "true" : "false").equals("true"); + useAndroidX = request.getArg( + "android.useAndroidX", + ((newFirebaseMessaging || decouplePlayServiceVersions || useGradle8) || (facebookSupported && compareVersions(facebookSdkVersion, "16.0.0") >= 0)) + ? "true" + : "false" + ).equals("true"); + if (!useAndroidX && newFirebaseMessaging) { + throw new BuildException("android.newFirebaseMessaging requires useAndroidX to be true. Please remove the android.useAndroidX build hint"); + } + log("useAndroidX: "+useAndroidX); + log("Compare facebookSdkVersion to 16.0.0: " + (compareVersions(facebookSdkVersion, "16.0.0") >= 0)); + log("Facebook supported: " + facebookSupported); migrateToAndroidX = useAndroidX && request.getArg("android.migrateToAndroidX", "true").equals("true"); buildToolsVersionInt = maxBuildToolsVersionInt; + this.buildToolsVersion = request.getArg("android.buildToolsVersion", ""+maxBuildToolsVersion); String buildToolsVersionIntStr = this.buildToolsVersion; if (buildToolsVersionIntStr.indexOf(".") > 1) { buildToolsVersionIntStr = buildToolsVersionIntStr.substring(0, buildToolsVersionIntStr.indexOf(".")); } buildToolsVersionInt = Integer.parseInt(buildToolsVersionIntStr.replaceAll("[^0-9]", "")); + if (newFirebaseMessaging) { + buildToolsVersionInt = 33; + } if (useAndroidX && buildToolsVersionInt < 29) { buildToolsVersionInt = 29; this.buildToolsVersion = "29"; @@ -872,14 +959,17 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc File googleServicesJson = new File(appDir, "google-services.json"); googleServicesJson = new File(libsDir.getParentFile(), "google-services.json"); - - try { - if (!retrolambda(new File(System.getProperty("user.dir")), request, dummyClassesDir)) { - return false; + if (!useJava8SourceLevel) { + log("Running retrolambda on classes to support Java 6 source level. Use the android.java8=true build hint to use Java 8 source level directly on Android, and avoid this step."); + try { + if (!retrolambda(new File(System.getProperty("user.dir")), request, dummyClassesDir)) { + return false; + } + } catch (Exception ex) { + throw new BuildException("Failed to run retrolambda on classes", ex); } - } catch (Exception ex) { - throw new BuildException("Failed to run retrolambda on classes", ex); } + String additionalImports = request.getArg("android.activityClassImports", ""); String additionalMembers = request.getArg("android.activityClassBody", ""); String additionalKeyVals = ""; @@ -910,12 +1000,7 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc String minSDK = request.getArg("android.min_sdk_version", "19"); - String facebookSupport = ""; - String facebookProguard = ""; - String facebookActivityMetaData = ""; - String facebookActivity = ""; - String facebookHashCode = ""; - boolean facebookSupported = request.getArg("facebook.appId", null) != null; + if (facebookSupported) { facebookHashCode = " try {\n" + " android.content.pm.PackageInfo info = getPackageManager().getPackageInfo(\n" @@ -948,6 +1033,9 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc facebookActivityMetaData = " \n"; + if (facebookClientToken != null) { + facebookActivityMetaData += " \n"; + } facebookActivity = " \n"; additionalKeyVals += "" + request.getArg("facebook.appId", "706695982682332") + ""; } @@ -1158,8 +1246,23 @@ public void usesClassMethod(String cls, String method) { } } request.putArgument("android.playServicesVersion", playServicesVersion); - request.putArgument("android.firebaseCoreVersion", request.getArg("android.firebaseCoreVersion", getDefaultPlayServiceVersion("firebase-core"))); - request.putArgument("android.firebaseMessagingVersion", request.getArg("android.firebaseMessagingVersion", getDefaultPlayServiceVersion("firebase-messaging"))); + request.putArgument( + "android.firebaseCoreVersion", + request.getArg("android.firebaseCoreVersion", + newFirebaseMessaging + ? "21.1.1" + : getDefaultPlayServiceVersion("firebase-core") + ) + ); + request.putArgument( + "android.firebaseMessagingVersion", + request.getArg( + "android.firebaseMessagingVersion", + newFirebaseMessaging + ? "23.2.1" + : getDefaultPlayServiceVersion("firebase-messaging") + ) + ); debug("-----USING PLAY SERVICES VERSION "+playServicesVersion+"----"); @@ -1178,7 +1281,11 @@ public void usesClassMethod(String cls, String method) { } if (!request.getArg("android.topDependency", "").contains("com.google.gms:google-services")) { - request.putArgument("android.topDependency", request.getArg("android.topDependency", "") + "\n classpath 'com.google.gms:google-services:4.0.1'\n"); + if (gradleVersionInt >= 8) { + request.putArgument("android.topDependency", request.getArg("android.topDependency", "") + "\n classpath 'com.google.gms:google-services:4.3.15'\n"); + } else { + request.putArgument("android.topDependency", request.getArg("android.topDependency", "") + "\n classpath 'com.google.gms:google-services:4.0.1'\n"); + } } if (!request.getArg("android.xgradle", "").contains("apply plugin: 'com.google.gms.google-services'")) { request.putArgument("android.xgradle", request.getArg("android.xgradle", "") + "\napply plugin: 'com.google.gms.google-services'\n"); @@ -2418,7 +2525,12 @@ public void usesClassMethod(String cls, String method) { + facebookHashCode + facebookSupport + streamMode - + registerNativeImplementationsAndCreateStubs(new URLClassLoader(new URL[]{codenameOneJar.toURI().toURL()}), srcDir, dummyClassesDir) + + registerNativeImplementationsAndCreateStubs( + new URLClassLoader( + new URL[]{ + dummyClassesDir.toURI().toURL(), + codenameOneJar.toURI().toURL() + }), srcDir, dummyClassesDir) + oncreate + "\n" + createOnCreateCode(request) + " }\n" @@ -2463,39 +2575,71 @@ public void usesClassMethod(String cls, String method) { String fcmRegisterPushCode = ""; if (useFCM) { - fcmRegisterPushCode = "try {\n" + - "\n" + - " String token = com.google.firebase.iid.FirebaseInstanceId.getInstance().getToken();\n" + - " if (token != null) {\n" + - " com.codename1.io.Preferences.set(\"push_key\", \"cn1-fcm-\"+token);\n" + - " if (i instanceof PushCallback) {\n" + - " ((PushCallback)i).registeredForPush(\"cn1-fcm-\"+token);\n" + - " }\n" + - " } else {\n" + - " java.util.Timer timer = new java.util.Timer();\n" + - " timer.schedule(new java.util.TimerTask() {\n" + - " public void run() {\n" + - " runOnUiThread(new Runnable() {\n" + - " public void run() {\n" + - " String token = com.google.firebase.iid.FirebaseInstanceId.getInstance().getToken();\n" + - " if (token != null) {\n" + - " com.codename1.io.Preferences.set(\"push_key\", \"cn1-fcm-\" + token);\n" + - " if (i instanceof PushCallback) {\n" + - " ((PushCallback) i).registeredForPush(\"cn1-fcm-\" + token);\n" + - " }\n" + - " }\n" + - " }\n" + - " });\n" + - " }\n" + - " }, 2000);\n" + - " }\n" + - " } catch (Exception ex) {\n" + - " if (i instanceof PushCallback) {\n" + - " ((PushCallback)i).pushRegistrationError(\"Failed to register push: \"+ex.getMessage(), 0);\n" + - " }\n" + - " System.out.println(\"Failed to get fcm token.\");\n" + - " ex.printStackTrace();\n" + - " }"; + if (newFirebaseMessaging) { + // The old FirebaseInstanceId class was deprecated in version 20.1.0, + // and can no longer be used so we need to update our callback to use newer APIs. + fcmRegisterPushCode = "com.google.firebase.messaging.FirebaseMessaging.getInstance().getToken()\n" + + " .addOnCompleteListener(new com.google.android.gms.tasks.OnCompleteListener() {\n" + + " @Override\n" + + " public void onComplete(com.google.android.gms.tasks.Task task) {\n" + + " if (!task.isSuccessful()) {\n" + + " if (i instanceof PushCallback) {\n" + + " ((PushCallback)i).pushRegistrationError(\"Failed to register push: \"+task.getException().getMessage(), 0);\n" + + " }\n" + + " return;\n" + + " }\n" + + " // Get the token\n" + + " String token = task.getResult();\n" + + " try {\n" + + " com.codename1.io.Preferences.set(\"push_key\", \"cn1-fcm-\"+token);\n" + + " if (i instanceof PushCallback) {\n" + + " ((PushCallback)i).registeredForPush(\"cn1-fcm-\"+token);\n" + + " }\n" + + "\n" + + " } catch (Exception ex) {\n" + + " if (i instanceof PushCallback) {\n" + + " ((PushCallback)i).pushRegistrationError(\"Failed to register push: \"+ex.getMessage(), 0);\n" + + " }\n" + + " System.out.println(\"Failed to get fcm token.\");\n" + + " ex.printStackTrace();\n" + + " }\n" + + " }\n" + + " });"; + } else { + fcmRegisterPushCode = "try {\n" + + "\n" + + " String token = com.google.firebase.iid.FirebaseInstanceId.getInstance().getToken();\n" + + " if (token != null) {\n" + + " com.codename1.io.Preferences.set(\"push_key\", \"cn1-fcm-\"+token);\n" + + " if (i instanceof PushCallback) {\n" + + " ((PushCallback)i).registeredForPush(\"cn1-fcm-\"+token);\n" + + " }\n" + + " } else {\n" + + " java.util.Timer timer = new java.util.Timer();\n" + + " timer.schedule(new java.util.TimerTask() {\n" + + " public void run() {\n" + + " runOnUiThread(new Runnable() {\n" + + " public void run() {\n" + + " String token = com.google.firebase.iid.FirebaseInstanceId.getInstance().getToken();\n" + + " if (token != null) {\n" + + " com.codename1.io.Preferences.set(\"push_key\", \"cn1-fcm-\" + token);\n" + + " if (i instanceof PushCallback) {\n" + + " ((PushCallback) i).registeredForPush(\"cn1-fcm-\" + token);\n" + + " }\n" + + " }\n" + + " }\n" + + " });\n" + + " }\n" + + " }, 2000);\n" + + " }\n" + + " } catch (Exception ex) {\n" + + " if (i instanceof PushCallback) {\n" + + " ((PushCallback)i).pushRegistrationError(\"Failed to register push: \"+ex.getMessage(), 0);\n" + + " }\n" + + " System.out.println(\"Failed to get fcm token.\");\n" + + " ex.printStackTrace();\n" + + " }"; + } } try { stubSourceCode += @@ -3017,7 +3161,11 @@ public void usesClassMethod(String cls, String method) { String keepOverride = request.getArg("android.proguardKeepOverride", "Exceptions, InnerClasses, Signature, Deprecated, SourceFile, LineNumberTable, *Annotation*, EnclosingMethod"); - + String keepFirebase = ""; + if (newFirebaseMessaging) { + keepFirebase = "-keep class com.google.android.gms.** { *; }\n\n" + + "-keep class com.google.firebase.** { *; }\n\n"; + } // workaround broken optimizer in proguard String proguardConfigOverride = "-dontusemixedcaseclassnames\n" + "-dontskipnonpubliclibraryclasses\n" @@ -3027,6 +3175,7 @@ public void usesClassMethod(String cls, String method) { + dontObfuscate + "\n" + "-dontwarn com.google.android.gms.**\n" + + keepFirebase + "-keep class com.codename1.impl.android.AndroidBrowserComponentCallback {\n" + "*;\n" + "}\n\n" @@ -3107,6 +3256,8 @@ public void usesClassMethod(String cls, String method) { HashMap env = new HashMap(); env.put("ANDROID_HOME", androidSDKDir.getAbsolutePath()); env.put("SLAVE_AAPT_TIMEOUT", "20"); + env.put("JAVA_HOME", getGradleJavaHome()); + request.putArgument("var.android.playServicesVersion", playServicesVersion); String additionalDependencies = request.getArg("gradleDependencies", ""); if (facebookSupported) { @@ -3115,7 +3266,7 @@ public void usesClassMethod(String cls, String method) { compile = "implementation"; } minSDK = maxInt("15", minSDK); - String facebookSdkVersion = request.getArg("android.facebookSdkVersion", "4.39.0");; + if(request.getArg("android.excludeBolts", "false").equals("true")) { additionalDependencies += " "+compile+" ('com.facebook.android:facebook-android-sdk:" + @@ -3137,7 +3288,11 @@ public void usesClassMethod(String cls, String method) { additionalDependencies += " "+compile+" 'com.google.android.gms:play-services-plus:"+getDefaultPlayServiceVersion("plus")+"'\n"; } if(playServicesAuth){ - additionalDependencies += " "+compile+" 'com.google.android.gms:play-services-auth:"+getDefaultPlayServiceVersion("auth")+"'\n"; + String playServiceAuthVersion = newFirebaseMessaging + ? "20.6.0" + : getDefaultPlayServiceVersion("auth"); + + additionalDependencies += " "+compile+" 'com.google.android.gms:play-services-auth:"+playServiceAuthVersion+"'\n"; } if(playServicesBase){ additionalDependencies += " "+compile+" 'com.google.android.gms:play-services-base:"+getDefaultPlayServiceVersion("base")+"'\n"; @@ -3211,17 +3366,17 @@ public void usesClassMethod(String cls, String method) { String multidex = ""; if (request.getArg("android.multidex", "true").equals("true")) { multidex = " multiDexEnabled true\n"; + String multidexVersion = newFirebaseMessaging || useGradle8 ? "2.0.1" : "1.0.3"; if (Integer.parseInt(minSDK) < 21) { if (useAndroidX) { if (!additionalDependencies.contains("androidx.multidex:multidex") && !request.getArg("android.gradleDep", "").contains("androidx.multidex:multidex")) { - additionalDependencies += " implementation 'androidx.multidex:multidex:1.0.3'\n"; + additionalDependencies += " implementation 'androidx.multidex:multidex:" + multidexVersion + "'\n"; } } else { if (!additionalDependencies.contains("com.android.support:multidex") && !request.getArg("android.gradleDep", "").contains("com.android.support:multidex")) { - additionalDependencies += " implementation 'com.android.support:multidex:1.0.3'\n"; + additionalDependencies += " implementation 'com.android.support:multidex:" + multidexVersion + "'\n"; } } - } } @@ -3235,23 +3390,18 @@ public void usesClassMethod(String cls, String method) { } else { gradleDependency = "classpath 'com.android.tools.build:gradle:3.0.1'\n"; } - }else { + }else if (gradleVersionInt < 8) { gradleDependency = "classpath 'com.android.tools.build:gradle:4.1.1'\n"; + } else { + gradleDependency = "classpath 'com.android.tools.build:gradle:8.1.0'\n"; } } gradleDependency += request.getArg("android.topDependency", ""); String compileSdkVersion = "'android-21'"; - String quotedBuildToolsVersion = "'23.0.1'"; - - compileSdkVersion = "'android-" + request.getArg("android.sdkVersion", "23") + "'"; - quotedBuildToolsVersion = "'" +buildToolsVersion + "'"; - - - String java8P2 = ""; - if(request.getArg("android.java8", "false").equals("true")) { + if(useJava8SourceLevel) { java8P2 = " compileOptions {\n" + " sourceCompatibility JavaVersion.VERSION_1_8\n" + " targetCompatibility JavaVersion.VERSION_1_8\n" + @@ -3274,8 +3424,10 @@ public void usesClassMethod(String cls, String method) { } } + + Properties gradlePropertiesObject = new Properties(); - File gradlePropertiesFile = new File(projectDir, "gradle.properties"); + File gradlePropertiesFile = new File(projectDir.getParentFile(), "gradle.properties"); if (gradlePropertiesFile.exists()) { try { FileInputStream fi = new FileInputStream(gradlePropertiesFile); @@ -3329,7 +3481,24 @@ public void usesClassMethod(String cls, String method) { if (!useAndroidX) { supportV4Default = " compile 'com.android.support:support-v4:"+supportLibVersion+".+'\n implementation 'com.android.support:appcompat-v7:"+supportLibVersion+".+'\n"; } else { - supportV4Default = " implementation 'androidx.legacy:legacy-support-v4:1.0.0'\n implementation 'androidx.appcompat:appcompat:" + request.getArg("androidx.appcompat.version", "1.0.0")+"'\n"; + String appCompatVersionDefault = "1.0.0"; + if (useGradle8) { + appCompatVersionDefault = "1.6.1"; + } + supportV4Default = " implementation 'androidx.legacy:legacy-support-v4:1.0.0'\n implementation 'androidx.appcompat:appcompat:" + request.getArg("androidx.appcompat.version", appCompatVersionDefault)+"'\n"; + + } + + String buildFeatures = ""; + if (useGradle8) { + buildFeatures = "buildFeatures {\n" + + " aidl true\n" + + " }\n"; + } + + String namespace = ""; + if (useGradle8) { + namespace = "namespace '"+request.getPackageName()+"'\n"; } String gradleProps = "apply plugin: 'com.android.application'\n" @@ -3399,6 +3568,8 @@ public void usesClassMethod(String cls, String method) { + " signingConfig signingConfigs.release\n" + " }\n"):"") + " }\n" + + buildFeatures + + namespace + "}\n" + "\n" + "repositories {\n" @@ -3441,10 +3612,14 @@ public void usesClassMethod(String cls, String method) { } gradlePropertiesObject.setProperty("org.gradle.daemon", "true"); - if(request.getArg("android.forceJava8Builder", "false").equals("true")) { - gradlePropertiesObject.setProperty("org.gradle.java.home", System.getProperty("java.home")); + if(useGradle8 || request.getArg("android.forceJava8Builder", "false").equals("true")) { + gradlePropertiesObject.setProperty("org.gradle.java.home", getGradleJavaHome()); + } + if (useGradle8) { + gradlePropertiesObject.setProperty("org.gradle.jvmargs", "-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"); + } else { + gradlePropertiesObject.setProperty("org.gradle.jvmargs", "-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"); } - gradlePropertiesObject.setProperty("org.gradle.jvmargs", "-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"); if (useAndroidX) { gradlePropertiesObject.setProperty("android.useAndroidX", "true"); gradlePropertiesObject.setProperty("android.enableJetifier", "true");