Android API 25 Changing language at runtime

168 views Asked by At

I am trying to change the language at runtime. It worked great on API 29 (android version 10). I need to make it work on a Nougat 7.1.1 (API 25). It has been a nightmare. If I have to change device language through Settings .., it works. I get to see the correct drawables and strings (strings.xml)

My goal is to make the language switch happen at runtime.

I am calling activity.recreate() in onResume(). The screen goes black. I am getting an exception and it points to the onCreate method at line 58. This is my onCreate and onResume methods:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);    // this is the line 58
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


...
}



@Override
    protected void onResume() {
        super.onResume();
        hideSystemUI();
        prepareVideoPlayback();

       locale = new Locale("en");

       recreate();
    }

2020-03-14 23:49:32.400 13533-13533/com.example.plasmavietiles W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter androidx.vectordrawable.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable 2020-03-14 23:49:32.422 13533-13533/com.example.plasmavietiles I/art: Rejecting re-init on previously-failed class java.lang.Class: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener; ... Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.example.plasmavietiles-2/base.apk"],nativeLibraryDirectories=[/data/app/com.example.plasmavietiles-2/lib/x86_64, /system/lib64, /vendor/lib64]] 2020-03-14 22:54:12.325 5972-5972/com.example.plasmavietiles I/art: at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56) 2020-03-14 22:54:12.325 5972-5972/com.example.plasmavietiles I/art: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380) 2020-03-14 22:54:12.325 5972-5972/com.example.plasmavietiles I/art: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312) 2020-03-14 22:54:12.325 5972-5972/com.example.plasmavietiles I/art: at void androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener) (ViewCompat.java:2421) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:779) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:659) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:552) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:161) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void com.example.plasmavietiles.MainActivity.onCreate(android.os.Bundle) (MainActivity.java:58) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6679) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1118) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2618) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2726) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1477) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.os.Looper.loop() (Looper.java:154) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6119) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:886) 2020-03-14 22:54:12.326 5972-5972/com.example.plasmavietiles I/art: at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:776) 2020-03-14 22:54:13.956 5972-5983/com.example.plasmavietiles I/art: Background partial concurrent mark sweep GC freed 21(800B) AllocSpace objects, 0(0B) LOS objects, 2

3

There are 3 answers

1
Anton Astafiev On

Probably, you still use more recent API. That's why newer classes were not found. I don't understand completely how you make API level switching at ft.

2
Ben P. On

From your updated code, it looks like you call recreate() every time in your onResume() method. This will essentially lead to an infinite loop:

  • Activity is launched and runs through the various lifecycle methods
  • onResume() is called
  • recreate() is called
  • Activity is restarted and runs through the various lifecycle methods
  • onResume() is called
  • recreate() is called
  • ...

You'll have to come up with some way to only call recreate() when necessary.

0
Nesan Mano On

I have found the answer to my own question

OnUnhandledKeyEventListener is not part of any APIs the older than API 28. In other words the device has to run Androdi API >=28.

This is an issue if you use AndroidX on devices with API < 28. To solve the problem if you are using an API <28 you simply have to make sure that your Activity call inherits from Activity and not AppCompatActivity.

Replace this public class MainActivity extends AppCompatActivity

with

public class MainActivity extends Activity