From 1c645f38b061336f538eadd6ffa4fd448e356524 Mon Sep 17 00:00:00 2001 From: Zeeshan Date: Thu, 21 Jun 2018 17:51:26 +0500 Subject: [PATCH 1/5] Android Oreo Issues Has Been Resolved. Process Phoenix Has Been Added for restarting Application work better then refresh method.... --- app/build.gradle | 20 +-- .../ahmedjazzar/rosetta/app/BaseActivity.java | 29 ++++ .../ahmedjazzar/rosetta/app/MainActivity.java | 2 +- app/src/main/res/values-v21/styles.xml | 2 +- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- rosetta/build.gradle | 29 ++-- rosetta/src/main/AndroidManifest.xml | 9 +- .../ahmedjazzar/rosetta/ContextWrapper.java | 42 ++++++ .../rosetta/LanguagesListDialogFragment.java | 3 +- .../com/ahmedjazzar/rosetta/LocalesUtils.java | 3 +- .../ahmedjazzar/rosetta/ProcessPhoenix.java | 131 ++++++++++++++++++ 12 files changed, 245 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java create mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/ContextWrapper.java create mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java diff --git a/app/build.gradle b/app/build.gradle index 7faf0a4..741e2b0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 27 + buildToolsVersion "27.0.3" defaultConfig { applicationId "com.ahmedjazzar.rosetta.app" - minSdkVersion 14 - targetSdkVersion 23 + minSdkVersion 15 + targetSdkVersion 27 versionCode 1 versionName "0.9.3" } @@ -20,12 +20,12 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:23.1.1' - compile 'com.android.support:design:23.1.1' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support:design:27.1.1' - testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:1.10.19' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:2.7.22' - compile project(':rosetta') + implementation project(':rosetta') } diff --git a/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java b/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java new file mode 100644 index 0000000..fea6cd9 --- /dev/null +++ b/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java @@ -0,0 +1,29 @@ +package com.ahmedjazzar.rosetta.app; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; + +import com.ahmedjazzar.rosetta.ContextWrapper; + +import java.util.Locale; + +public abstract class BaseActivity extends AppCompatActivity { + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } + + @Override + protected void attachBaseContext(Context newBase) { + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(newBase); + Locale locale = new Locale(mSharedPreferences.getString("user_preferred_language", "en")); + Context context = ContextWrapper.wrap(newBase, locale); + super.attachBaseContext(context); + } +} diff --git a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java index a50dc17..744f98a 100644 --- a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java +++ b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java @@ -12,7 +12,7 @@ import java.util.Locale; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index 251fb9f..05c4277 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -4,6 +4,6 @@ false true true - @android:color/transparent + @color/colorPrimaryDark diff --git a/build.gradle b/build.gradle index e0b366a..ad6a928 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,10 @@ buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:3.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -15,6 +16,7 @@ buildscript { allprojects { repositories { jcenter() + google() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f23df6e..2a0e35e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Oct 21 11:34:03 PDT 2015 +#Thu Jun 21 17:34:17 PKT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/rosetta/build.gradle b/rosetta/build.gradle index 82563f1..d3e6146 100644 --- a/rosetta/build.gradle +++ b/rosetta/build.gradle @@ -14,7 +14,7 @@ ext { siteUrl = 'https://github.com/ahmedaljazzar/rosetta' gitUrl = 'https://github.com/ahmedaljazzar/rosetta.git' - libraryVersion = '1.0.1' + libraryVersion = '1.0.2' developerId = 'ahmedaljazzar' developerName = 'Ahmed Jazzar' @@ -29,11 +29,12 @@ buildscript { repositories { jcenter() mavenCentral() + google() } dependencies { - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4' - classpath 'com.android.tools.build:gradle:1.2.3' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' + classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' } } @@ -45,12 +46,12 @@ android { maven { url 'http://repo1.maven.org/maven2' } } - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { - minSdkVersion 14 - targetSdkVersion 23 + minSdkVersion 15 + targetSdkVersion 27 versionCode 3 versionName "1.0.1" } @@ -64,11 +65,11 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:1.10.19' - compile 'com.android.support:appcompat-v7:23.1.1' + implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:2.7.22' + implementation 'com.android.support:appcompat-v7:27.1.1' } -apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' -apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' \ No newline at end of file +//apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' +//apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' \ No newline at end of file diff --git a/rosetta/src/main/AndroidManifest.xml b/rosetta/src/main/AndroidManifest.xml index f1b2707..bf7f3cb 100644 --- a/rosetta/src/main/AndroidManifest.xml +++ b/rosetta/src/main/AndroidManifest.xml @@ -1,5 +1,10 @@ +package="com.ahmedjazzar.rosetta"> - + + + diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/ContextWrapper.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/ContextWrapper.java new file mode 100644 index 0000000..b94a94f --- /dev/null +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/ContextWrapper.java @@ -0,0 +1,42 @@ +package com.ahmedjazzar.rosetta; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.LocaleList; + +import java.util.Locale; + +public class ContextWrapper extends android.content.ContextWrapper { + + public ContextWrapper(Context base) { + super(base); + } + + public static ContextWrapper wrap(Context context, Locale newLocale) { + + Resources res = context.getResources(); + Configuration configuration = res.getConfiguration(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + configuration.setLocale(newLocale); + + LocaleList localeList = new LocaleList(newLocale); + LocaleList.setDefault(localeList); + configuration.setLocales(localeList); + + context = context.createConfigurationContext(configuration); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + configuration.setLocale(newLocale); + context = context.createConfigurationContext(configuration); + + } else { + configuration.locale = newLocale; + res.updateConfiguration(configuration, res.getDisplayMetrics()); + } + + return new ContextWrapper(context); + } +} diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java index 07f3a5f..dba3bc0 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java @@ -153,7 +153,8 @@ protected void onPositiveClick() { getActivity(), mSelectedLanguage)) { mLogger.info("App locale changed successfully."); - LocalesUtils.refreshApplication(getActivity()); + //LocalesUtils.refreshApplication(getActivity()); + ProcessPhoenix.triggerRebirth(getActivity()); } else { mLogger.error("Unsuccessful trial to change the App locale."); // TODO: notify the user that his request not placed diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java index b06b178..b907729 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java @@ -265,7 +265,8 @@ static boolean setLocale(Locale newLocale, Activity activity) { } if (LocalesUtils.setAppLocale(activity.getApplicationContext(), newLocale)) { - LocalesUtils.refreshApplication(activity); + //LocalesUtils.refreshApplication(activity); + ProcessPhoenix.triggerRebirth(activity); return true; } diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java new file mode 100644 index 0000000..c283316 --- /dev/null +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014 Jake Wharton + * + * 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.ahmedjazzar.rosetta; + +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Process; +import android.support.v7.app.AppCompatActivity; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + +/** + * Process Phoenix facilitates restarting your application process. This should only be used for + * things like fundamental state changes in your debug builds (e.g., changing from staging to + * production). + *

+ * Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance. + */ +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Process; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + +/** + * Process Phoenix facilitates restarting your application process. This should only be used for + * things like fundamental state changes in your debug builds (e.g., changing from staging to + * production). + *

+ * Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance. + */ +public final class ProcessPhoenix extends AppCompatActivity { + private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents"; + + /** + * Call to restart the application process using the {@linkplain Intent#CATEGORY_DEFAULT default} + * activity as an intent. + *

+ * Behavior of the current process after invoking this method is undefined. + */ + public static void triggerRebirth(Context context) { + triggerRebirth(context, getRestartIntent(context)); + } + + /** + * Call to restart the application process using the specified intents. + *

+ * Behavior of the current process after invoking this method is undefined. + */ + public static void triggerRebirth(Context context, Intent... nextIntents) { + Intent intent = new Intent(context, ProcessPhoenix.class); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context. + intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents))); + context.startActivity(intent); + if (context instanceof Activity) { + ((Activity) context).finish(); + } + Runtime.getRuntime().exit(0); // Kill kill kill! + } + + private static Intent getRestartIntent(Context context) { + String packageName = context.getPackageName(); + Intent defaultIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); + if (defaultIntent != null) { + defaultIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); + return defaultIntent; + } + + throw new IllegalStateException("Unable to determine default activity for " + + packageName + + ". Does an activity specify the DEFAULT category in its intent filter?"); + } + + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ArrayList intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS); + startActivities(intents.toArray(new Intent[intents.size()])); + finish(); + Runtime.getRuntime().exit(0); // Kill kill kill! + } + + /** + * Checks if the current process is a temporary Phoenix Process. + * This can be used to avoid initialisation of unused resources or to prevent running code that + * is not multi-process ready. + * + * @return true if the current process is a temporary Phoenix Process + */ + public static boolean isPhoenixProcess(Context context) { + int currentPid = Process.myPid(); + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List runningProcesses = manager.getRunningAppProcesses(); + if (runningProcesses != null) { + for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { + if (processInfo.pid == currentPid && processInfo.processName.endsWith(":phoenix")) { + return true; + } + } + } + return false; + } +} \ No newline at end of file From 7857e402f1042f5620a6975348e8540afdecc196 Mon Sep 17 00:00:00 2001 From: Zeeshan Date: Fri, 22 Jun 2018 16:24:38 +0500 Subject: [PATCH 2/5] CodeCleaned up --- .../main/java/com/ahmedjazzar/rosetta/app/MainActivity.java | 4 ++-- .../java/com/ahmedjazzar/rosetta/app/MainApplication.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java index 744f98a..93b1098 100644 --- a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java +++ b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java @@ -18,10 +18,10 @@ public class MainActivity extends BaseActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + Toolbar toolbar = findViewById(R.id.toolbar); // This floating button switching between Arabic and English Locales manually upon click - final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + final FloatingActionButton fab = findViewById(R.id.fab); setSupportActionBar(toolbar); if (MainApplication.languageSwitcher.getCurrentLocale().getLanguage().equals("ar")) { diff --git a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainApplication.java b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainApplication.java index 02db5e2..899249b 100644 --- a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainApplication.java +++ b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainApplication.java @@ -1,7 +1,11 @@ package com.ahmedjazzar.rosetta.app; import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import com.ahmedjazzar.rosetta.ContextWrapper; import com.ahmedjazzar.rosetta.LanguageSwitcher; import java.util.HashSet; From b59f924e4dcdc32a2b719598fe8de445d9e04b12 Mon Sep 17 00:00:00 2001 From: Zeeshan Date: Fri, 29 Jun 2018 19:28:39 +0500 Subject: [PATCH 3/5] Removed Process Phoenix and Added as Dependency --- app/src/main/AndroidManifest.xml | 6 +- rosetta/build.gradle | 1 + rosetta/src/main/AndroidManifest.xml | 9 +- .../rosetta/LanguagesListDialogFragment.java | 2 + .../com/ahmedjazzar/rosetta/LocalesUtils.java | 2 + .../ahmedjazzar/rosetta/ProcessPhoenix.java | 131 ------------------ 6 files changed, 10 insertions(+), 141 deletions(-) delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7b04df9..badd523 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,12 +3,12 @@ package="com.ahmedjazzar.rosetta.app"> + android:theme="@style/AppTheme"> - + diff --git a/rosetta/build.gradle b/rosetta/build.gradle index d3e6146..f6d27c0 100644 --- a/rosetta/build.gradle +++ b/rosetta/build.gradle @@ -69,6 +69,7 @@ dependencies { testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.7.22' implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.jakewharton:process-phoenix:2.0.0' } //apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' diff --git a/rosetta/src/main/AndroidManifest.xml b/rosetta/src/main/AndroidManifest.xml index bf7f3cb..6cdeb08 100644 --- a/rosetta/src/main/AndroidManifest.xml +++ b/rosetta/src/main/AndroidManifest.xml @@ -1,10 +1,5 @@ + package="com.ahmedjazzar.rosetta"> - - - + diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java index dba3bc0..1abeaf8 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java @@ -11,6 +11,8 @@ import android.widget.Button; import android.widget.TextView; +import com.jakewharton.processphoenix.ProcessPhoenix; + import java.util.ArrayList; import java.util.Locale; diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java index b907729..f77ed9a 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java @@ -10,6 +10,8 @@ import android.support.v4.app.FragmentActivity; import android.util.DisplayMetrics; +import com.jakewharton.processphoenix.ProcessPhoenix; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java deleted file mode 100644 index c283316..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/ProcessPhoenix.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2014 Jake Wharton - * - * 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.ahmedjazzar.rosetta; - -import android.app.Activity; -import android.app.ActivityManager; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Process; -import android.support.v7.app.AppCompatActivity; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; -import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; - -/** - * Process Phoenix facilitates restarting your application process. This should only be used for - * things like fundamental state changes in your debug builds (e.g., changing from staging to - * production). - *

- * Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance. - */ -import android.app.Activity; -import android.app.ActivityManager; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Process; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; -import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; - -/** - * Process Phoenix facilitates restarting your application process. This should only be used for - * things like fundamental state changes in your debug builds (e.g., changing from staging to - * production). - *

- * Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance. - */ -public final class ProcessPhoenix extends AppCompatActivity { - private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents"; - - /** - * Call to restart the application process using the {@linkplain Intent#CATEGORY_DEFAULT default} - * activity as an intent. - *

- * Behavior of the current process after invoking this method is undefined. - */ - public static void triggerRebirth(Context context) { - triggerRebirth(context, getRestartIntent(context)); - } - - /** - * Call to restart the application process using the specified intents. - *

- * Behavior of the current process after invoking this method is undefined. - */ - public static void triggerRebirth(Context context, Intent... nextIntents) { - Intent intent = new Intent(context, ProcessPhoenix.class); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context. - intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents))); - context.startActivity(intent); - if (context instanceof Activity) { - ((Activity) context).finish(); - } - Runtime.getRuntime().exit(0); // Kill kill kill! - } - - private static Intent getRestartIntent(Context context) { - String packageName = context.getPackageName(); - Intent defaultIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); - if (defaultIntent != null) { - defaultIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); - return defaultIntent; - } - - throw new IllegalStateException("Unable to determine default activity for " - + packageName - + ". Does an activity specify the DEFAULT category in its intent filter?"); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ArrayList intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS); - startActivities(intents.toArray(new Intent[intents.size()])); - finish(); - Runtime.getRuntime().exit(0); // Kill kill kill! - } - - /** - * Checks if the current process is a temporary Phoenix Process. - * This can be used to avoid initialisation of unused resources or to prevent running code that - * is not multi-process ready. - * - * @return true if the current process is a temporary Phoenix Process - */ - public static boolean isPhoenixProcess(Context context) { - int currentPid = Process.myPid(); - ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - List runningProcesses = manager.getRunningAppProcesses(); - if (runningProcesses != null) { - for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) { - if (processInfo.pid == currentPid && processInfo.processName.endsWith(":phoenix")) { - return true; - } - } - } - return false; - } -} \ No newline at end of file From e1f647bcdbdffa2a2c3beb1a179694f2497ae315 Mon Sep 17 00:00:00 2001 From: Zeeshan Rasool Date: Mon, 30 Mar 2020 15:50:47 +0400 Subject: [PATCH 4/5] Updated to AndroidX Component --- app/build.gradle | 16 +++++++--------- .../ahmedjazzar/rosetta/app/BaseActivity.java | 2 +- .../ahmedjazzar/rosetta/app/MainActivity.java | 10 +++------- app/src/main/res/layout/activity_main.xml | 12 ++++++------ build.gradle | 2 +- gradle.properties | 4 +++- gradle/wrapper/gradle-wrapper.properties | 4 ++-- rosetta/build.gradle | 18 +++++++++--------- .../ahmedjazzar/rosetta/LanguageSwitcher.java | 4 ++-- .../rosetta/LanguagesListDialogFragment.java | 5 ++--- .../com/ahmedjazzar/rosetta/LocalesUtils.java | 4 ++-- 11 files changed, 38 insertions(+), 43 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 741e2b0..daa2aa3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 27 - buildToolsVersion "27.0.3" + compileSdkVersion 29 + buildToolsVersion '29.0.3' defaultConfig { applicationId "com.ahmedjazzar.rosetta.app" minSdkVersion 15 - targetSdkVersion 27 + targetSdkVersion 29 versionCode 1 versionName "0.9.3" } @@ -21,11 +21,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support:design:27.1.1' - - testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:2.7.22' - + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.material:material:1.1.0' + testImplementation 'junit:junit:4.13' + testImplementation 'org.mockito:mockito-core:2.23.0' implementation project(':rosetta') } diff --git a/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java b/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java index fea6cd9..ba79b27 100644 --- a/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java +++ b/app/src/main/java/com/ahmedjazzar/rosetta/app/BaseActivity.java @@ -4,7 +4,7 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import com.ahmedjazzar.rosetta.ContextWrapper; diff --git a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java index 93b1098..78e10ca 100644 --- a/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java +++ b/app/src/main/java/com/ahmedjazzar/rosetta/app/MainActivity.java @@ -1,17 +1,13 @@ package com.ahmedjazzar.rosetta.app; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; -import com.ahmedjazzar.rosetta.LanguageSwitcher; - -import java.util.Locale; - public class MainActivity extends BaseActivity { @Override diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f554cbe..df1113e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - - - - + - - + diff --git a/build.gradle b/build.gradle index ad6a928..2d1d9aa 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.6.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle.properties b/gradle.properties index 1d3591c..915f0e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,6 @@ # When configured, Gradle will run in incubating parallel mode. # 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 \ No newline at end of file +# org.gradle.parallel=true +android.enableJetifier=true +android.useAndroidX=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2a0e35e..a7653d6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Jun 21 17:34:17 PKT 2018 +#Mon Mar 30 15:47:02 GST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/rosetta/build.gradle b/rosetta/build.gradle index f6d27c0..4cc8a54 100644 --- a/rosetta/build.gradle +++ b/rosetta/build.gradle @@ -32,9 +32,9 @@ buildscript { google() } dependencies { - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' - classpath 'com.android.tools.build:gradle:3.1.3' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' + classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } } @@ -46,12 +46,12 @@ android { maven { url 'http://repo1.maven.org/maven2' } } - compileSdkVersion 27 - buildToolsVersion '27.0.3' + compileSdkVersion 29 + buildToolsVersion '29.0.3' defaultConfig { minSdkVersion 15 - targetSdkVersion 27 + targetSdkVersion 29 versionCode 3 versionName "1.0.1" } @@ -66,9 +66,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:2.7.22' - implementation 'com.android.support:appcompat-v7:27.1.1' + testImplementation 'junit:junit:4.13' + testImplementation 'org.mockito:mockito-core:2.23.0' + implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.jakewharton:process-phoenix:2.0.0' } diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java index 3585593..927455d 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java @@ -2,8 +2,8 @@ import android.app.Activity; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v4.app.FragmentActivity; +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; import java.util.HashSet; import java.util.Locale; diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java index 1abeaf8..a9bbfdf 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java @@ -4,10 +4,9 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentActivity; import android.widget.Button; import android.widget.TextView; diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java index f77ed9a..762af4d 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java @@ -6,8 +6,8 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; -import android.support.annotation.NonNull; -import android.support.v4.app.FragmentActivity; +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; import android.util.DisplayMetrics; import com.jakewharton.processphoenix.ProcessPhoenix; From aa011ce58acc9344e26c950bc33e2de674120fef Mon Sep 17 00:00:00 2001 From: Zeeshan Rasool Date: Mon, 30 Mar 2020 15:55:29 +0400 Subject: [PATCH 5/5] Planning to update to Kotlin --- app/build.gradle | 7 ++ build.gradle | 2 + rosetta/build.gradle | 7 ++ .../rosetta/LanguagesListDialogFragment.java | 32 ++++---- .../rosetta/LocalesPreferenceManager.java | 48 ++++++----- .../com/ahmedjazzar/rosetta/LocalesUtils.java | 82 ++++++++----------- 6 files changed, 89 insertions(+), 89 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index daa2aa3..9a3ca55 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,6 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' android { compileSdkVersion 29 @@ -26,4 +28,9 @@ dependencies { testImplementation 'junit:junit:4.13' testImplementation 'org.mockito:mockito-core:2.23.0' implementation project(':rosetta') + implementation "androidx.core:core-ktx:1.2.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} +repositories { + mavenCentral() } diff --git a/build.gradle b/build.gradle index 2d1d9aa..91e48dd 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.3.71' repositories { jcenter() google() } dependencies { classpath 'com.android.tools.build:gradle:3.6.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/rosetta/build.gradle b/rosetta/build.gradle index 4cc8a54..c97175d 100644 --- a/rosetta/build.gradle +++ b/rosetta/build.gradle @@ -1,4 +1,6 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' ext { bintrayRepo = 'maven' @@ -70,6 +72,11 @@ dependencies { testImplementation 'org.mockito:mockito-core:2.23.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.jakewharton:process-phoenix:2.0.0' + implementation "androidx.core:core-ktx:1.2.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} +repositories { + mavenCentral() } //apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java index a9bbfdf..3781e67 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java @@ -5,8 +5,10 @@ import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; + import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentActivity; + import android.widget.Button; import android.widget.TextView; @@ -18,7 +20,7 @@ /** * This fragment is responsible for displaying the supported locales and performing any necessary * action that allows user to select, cancel, and commit changes. - * + *

* Created by ahmedjazzar on 1/19/16. */ @@ -32,12 +34,11 @@ public class LanguagesListDialogFragment extends DialogFragment { private int mSelectedLanguage = -1; private Logger mLogger; - public LanguagesListDialogFragment() { + public LanguagesListDialogFragment() { this.mLogger = new Logger(TAG); } /** - * * @param savedInstanceState * @return a Dialog fragment */ @@ -76,19 +77,19 @@ public void onClick(DialogInterface dialogInterface, int which) { } /** - * * @param which the position of the selected locale */ - protected void onLanguageSelected(int which) { + protected void onLanguageSelected(int which) { // just update the selected locale mSelectedLanguage = which; } /** * Localizing the dialog buttons and title + * * @param which the position of the selected locale */ - protected void onLanguageSelectedLocalized(int which) { + protected void onLanguageSelectedLocalized(int which) { // update the selected locale mSelectedLanguage = which; @@ -106,13 +107,14 @@ protected void onLanguageSelectedLocalized(int which) { /** * the position of the selected locale given the ids - * @param which the position of the selected locale - * @param titleView dialog's title text view + * + * @param which the position of the selected locale + * @param titleView dialog's title text view * @param positiveButton positive button * @param negativeButton negative button */ protected void onLanguageSelectedLocalized(int which, TextView titleView, Button positiveButton, - Button negativeButton) { + Button negativeButton) { // update the selected locale mSelectedLanguage = which; @@ -124,10 +126,10 @@ protected void onLanguageSelectedLocalized(int which, TextView titleView, Button "locale"); String LocalizedTitle = LocalesUtils.getInSpecificLocale(activity, locale, DIALOG_TITLE_ID); - if(titleView == null) { + if (titleView == null) { // Display dialog title in the selected locale dialog.setTitle(LocalizedTitle); - } else { + } else { titleView.setText(LocalizedTitle); } @@ -160,7 +162,7 @@ protected void onPositiveClick() { mLogger.error("Unsuccessful trial to change the App locale."); // TODO: notify the user that his request not placed } - } else { + } else { dismiss(); } } @@ -175,19 +177,17 @@ protected void onNegativeClick() { } /** - * * @return available languages */ protected String[] getLanguages() { - ArrayList languages = LocalesUtils.getLocalesWithDisplayName(); + ArrayList languages = LocalesUtils.getLocalesWithDisplayName(); return languages.toArray(new String[languages.size()]); } /** - * * @return the index of the locale that app is using now */ - protected int getCurrentLocaleIndex() { + protected int getCurrentLocaleIndex() { return LocalesUtils.getCurrentLocaleIndex(); } diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java index 7228a3b..04d30e8 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java @@ -10,47 +10,47 @@ * This class is responsible for setting and getting the preferred locale and manage any related * actions. I think that there's no need for logging here because the utils class already handles * logs for these actions based on their returned results. - * + *

* Created by ahmedjazzar on 1/22/16. */ -class LocalesPreferenceManager { +class LocalesPreferenceManager { private SharedPreferences mSharedPreferences; private SharedPreferences.Editor mEditor; - + static final int BASE_LOCALE = 1; private final String BASE_LANGUAGE_KEY = "base_language"; private final String BASE_COUNTRY_KEY = "base_country"; - + static final int LAUNCH_LOCALE = 2; private final String LAUNCH_LANGUAGE_KEY = "launch_language"; private final String LAUNCH_COUNTRY_KEY = "launch_country"; - + static final int USER_PREFERRED_LOCALE = 3; private final String USER_PREFERRED_LANGUAGE_KEY = "user_preferred_language"; private final String USER_PREFERRED_COUNTRY_KEY = "user_preferred_country"; - LocalesPreferenceManager(Context context, Locale firstLaunchLocale, Locale baseLocale) { + LocalesPreferenceManager(Context context, Locale firstLaunchLocale, Locale baseLocale) { this.mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); this.mEditor = this.mSharedPreferences.edit(); - if (!isLocaleExists(BASE_LOCALE)) { + if (!isLocaleExists(BASE_LOCALE)) { this.setPreferredLocale(BASE_LOCALE, baseLocale); } - if (!isLocaleExists(LAUNCH_LOCALE)) { + if (!isLocaleExists(LAUNCH_LOCALE)) { this.setPreferredLocale(LAUNCH_LOCALE, firstLaunchLocale); } - if (!isLocaleExists(USER_PREFERRED_LOCALE)) { + if (!isLocaleExists(USER_PREFERRED_LOCALE)) { this.setPreferredLocale(USER_PREFERRED_LOCALE, firstLaunchLocale); } } - boolean isLocaleExists(int key) { + boolean isLocaleExists(int key) { - switch (key) { + switch (key) { case BASE_LOCALE: return mSharedPreferences.contains(this.BASE_LANGUAGE_KEY); case LAUNCH_LOCALE: @@ -68,20 +68,19 @@ boolean isLocaleExists(int key) { * @param locale user desired locale * @return true if the preference updated */ - boolean setPreferredLocale(int key, Locale locale) { + boolean setPreferredLocale(int key, Locale locale) { return this.setPreferredLocale(key, locale.getLanguage(), locale.getCountry()); } /** - * * @return preferred locale after concatenating language and country */ - Locale getPreferredLocale(int key) { + Locale getPreferredLocale(int key) { String languageKey; String countryKey; - switch (key) { + switch (key) { case BASE_LOCALE: languageKey = this.BASE_LANGUAGE_KEY; countryKey = this.BASE_COUNTRY_KEY; @@ -101,7 +100,7 @@ Locale getPreferredLocale(int key) { String language = getPreferredLanguage(languageKey); String country = getPreferredCountry(countryKey); - if (language == null) { + if (language == null) { return null; } @@ -111,16 +110,17 @@ Locale getPreferredLocale(int key) { /** * Sets user preferred locale by setting a language preference and a country preference since * there's no supported preferences for locales + * * @param language of the locale; ex. en - * @param country of the locale; ex. US + * @param country of the locale; ex. US * @return true if the preferences updated */ - private boolean setPreferredLocale(int key, String language, String country) { - + private boolean setPreferredLocale(int key, String language, String country) { + String languageKey; String countryKey; - switch (key) { + switch (key) { case BASE_LOCALE: languageKey = this.BASE_LANGUAGE_KEY; countryKey = this.BASE_COUNTRY_KEY; @@ -136,7 +136,7 @@ private boolean setPreferredLocale(int key, String language, String country) { default: return false; } - + mEditor.putString(languageKey, language); mEditor.putString(countryKey, country); @@ -144,18 +144,16 @@ private boolean setPreferredLocale(int key, String language, String country) { } /** - * * @return preferred language */ - private String getPreferredLanguage(String key) { + private String getPreferredLanguage(String key) { return mSharedPreferences.getString(key, null); } /** - * * @return preferred country */ - private String getPreferredCountry(String key) { + private String getPreferredCountry(String key) { return mSharedPreferences.getString(key, null); } } diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java index 762af4d..658e6c9 100644 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java +++ b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java @@ -6,8 +6,10 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; + import androidx.annotation.NonNull; import androidx.fragment.app.FragmentActivity; + import android.util.DisplayMetrics; import com.jakewharton.processphoenix.ProcessPhoenix; @@ -22,7 +24,7 @@ * This class is a helper class that connects all library classes activities together and make it * easier for every class in the library to use and look at the shared info without a need to * initialize a new object from the desired class - * + *

* Created by ahmedjazzar on 1/19/16. */ final class LocalesUtils { @@ -38,7 +40,6 @@ final class LocalesUtils { private static Logger sLogger = new Logger(TAG); /** - * * @param detector just a setter because I don't want to declare any constructors in this class */ static void setDetector(@NonNull LocalesDetector detector) { @@ -46,83 +47,77 @@ static void setDetector(@NonNull LocalesDetector detector) { } /** - * * @param localesPreferenceManager just a setter because I don't want to declare any * constructors in this class */ static void setLocalesPreferenceManager( - @NonNull LocalesPreferenceManager localesPreferenceManager) { + @NonNull LocalesPreferenceManager localesPreferenceManager) { LocalesUtils.sLocalesPreferenceManager = localesPreferenceManager; } /** - * * @param stringId a string to start discovering sLocales in * @return a HashSet of discovered sLocales */ - static HashSet fetchAvailableLocales(int stringId) { + static HashSet fetchAvailableLocales(int stringId) { return sDetector.fetchAvailableLocales(stringId); } /** - * * @param localesSet sLocales user wanna use */ - static void setSupportedLocales(HashSet localesSet) { + static void setSupportedLocales(HashSet localesSet) { LocalesUtils.sLocales = sDetector.validateLocales(localesSet); sLogger.debug("Locales have been changed"); } /** - * * @return a HashSet of the available sLocales discovered in the application */ - static HashSet getLocales() { + static HashSet getLocales() { return LocalesUtils.sLocales; } /** - * * @return a list of locales for displaying on the layout purposes */ - static ArrayList getLocalesWithDisplayName() { + static ArrayList getLocalesWithDisplayName() { ArrayList stringLocales = new ArrayList<>(); - for (Locale loc: LocalesUtils.getLocales()) { + for (Locale loc : LocalesUtils.getLocales()) { stringLocales.add(loc.getDisplayName(loc)); } return stringLocales; } /** - * * @return the index of the current app locale */ - static int getCurrentLocaleIndex() { + static int getCurrentLocaleIndex() { Locale locale = LocalesUtils.getCurrentLocale(); int index = -1; int itr = 0; - for (Locale l : sLocales) { - if(locale.equals(l)) { + for (Locale l : sLocales) { + if (locale.equals(l)) { index = itr; break; } itr++; } - if (index == -1) { + if (index == -1) { //TODO: change the index to the most closer available locale sLogger.warn("Current device locale '" + locale.toString() + "' does not appear in your given supported locales"); index = sDetector.detectMostClosestLocale(locale); - if(index == -1) { + if (index == -1) { index = 0; sLogger.warn("Current locale index changed to 0 as the current locale '" + - locale.toString() + - "' not supported." + locale.toString() + + "' not supported." ); } } @@ -131,40 +126,36 @@ static int getCurrentLocaleIndex() { } /** - * - * @see Pseudolocalization for - * more information about pseudo localization * @return pseudo locales list + * @see Pseudolocalization for + * more information about pseudo localization */ - static List getPseudoLocales() { + static List getPseudoLocales() { return Arrays.asList(LocalesUtils.PSEUDO_LOCALES); } /** - * * @param index * @return the locale at the given index */ - static Locale getLocaleFromIndex(int index) { + static Locale getLocaleFromIndex(int index) { return LocalesUtils.sLocales.toArray(new Locale[LocalesUtils.sLocales.size()])[index]; } /** - * * @param context - * @param index the selected locale position + * @param index the selected locale position * @return true if the application locale changed */ - static boolean setAppLocale(Context context, int index) { + static boolean setAppLocale(Context context, int index) { return setAppLocale(context, getLocaleFromIndex(index)); } /** - * * @param context * @return true if the application locale changed */ - static boolean setAppLocale(Context context, Locale newLocale) { + static boolean setAppLocale(Context context, Locale newLocale) { Resources resources = context.getResources(); DisplayMetrics displayMetrics = resources.getDisplayMetrics(); @@ -179,14 +170,14 @@ static boolean setAppLocale(Context context, Locale newLocale) { } resources.updateConfiguration(configuration, displayMetrics); - if(oldLocale.equals(newLocale)) { + if (oldLocale.equals(newLocale)) { return false; } - if (LocalesUtils.updatePreferredLocale(newLocale)) { + if (LocalesUtils.updatePreferredLocale(newLocale)) { sLogger.info("Locale preferences updated to: " + newLocale); Locale.setDefault(newLocale); - } else { + } else { sLogger.error("Failed to update locale preferences."); } @@ -194,15 +185,13 @@ static boolean setAppLocale(Context context, Locale newLocale) { } /** - * * @return application's base locale */ - static Locale getBaseLocale() { + static Locale getBaseLocale() { return LocalesUtils.sLocalesPreferenceManager.getPreferredLocale(LocalesPreferenceManager.BASE_LOCALE); } /** - * * @param activity * @param locale * @param stringId the target string @@ -219,7 +208,7 @@ static String getInSpecificLocale(FragmentActivity activity, Locale locale, int Resources resources = new Resources(activity.getAssets(), metrics, conf); conf.locale = old; - return resources.getString(stringId); + return resources.getString(stringId); } /** @@ -246,27 +235,26 @@ static void refreshApplication(Activity activity) { } /** - * * @return the first launch locale */ - static Locale getLaunchLocale() { + static Locale getLaunchLocale() { return sLocalesPreferenceManager.getPreferredLocale(LocalesPreferenceManager.LAUNCH_LOCALE); } /** * Setting the application locale manually - * @param newLocale the desired locale - * @param activity the current activity in order to refresh the app * + * @param newLocale the desired locale + * @param activity the current activity in order to refresh the app * @return true if the operation succeed, false otherwise */ static boolean setLocale(Locale newLocale, Activity activity) { - if (newLocale == null || !getLocales().contains(newLocale)) { + if (newLocale == null || !getLocales().contains(newLocale)) { return false; } - if (LocalesUtils.setAppLocale(activity.getApplicationContext(), newLocale)) { + if (LocalesUtils.setAppLocale(activity.getApplicationContext(), newLocale)) { //LocalesUtils.refreshApplication(activity); ProcessPhoenix.triggerRebirth(activity); return true; @@ -288,18 +276,16 @@ public static Locale getCurrentLocale(Context context) { } /** - * * @param locale the new preferred locale * @return true if the preferred locale updated */ - private static boolean updatePreferredLocale(Locale locale) { + private static boolean updatePreferredLocale(Locale locale) { return LocalesUtils.sLocalesPreferenceManager .setPreferredLocale(LocalesPreferenceManager.USER_PREFERRED_LOCALE, locale); } /** - * * @return current application locale */ private static Locale getCurrentLocale() {