Idan Zimbler
Idan Zimbler

Reputation: 75

Android application crashes at setContentView at OnCreate only on low android API

My application works at API 24 and above but crashes at API 19. the problem seem to be at setContentView line in the OnCreate method.

I tried to change all API 21+ features at android XML file but it didn't help. Also tried to put multidex and it didn't work.

I added here the setContentView method:

package com.idan.idanzimbler.epiclogin.view;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.idan.idanzimbler.epiclogin.R;
import com.idan.idanzimbler.epiclogin.controller.FillSeriesListFromFireBaseBySearchTask;
import com.idan.idanzimbler.epiclogin.controller.FillSeriesListFromFireBaseBySuggestionsTask;
import com.idan.idanzimbler.epiclogin.controller.FillSeriesListFromFireBaseTask;
import com.idan.idanzimbler.epiclogin.controller.TvSeriesFavoriteList;
import com.idan.idanzimbler.epiclogin.controller.TvSeriesHomeList;
import com.idan.idanzimbler.epiclogin.controller.UsersBookmarks;
import com.idan.idanzimbler.epiclogin.modle.TvSeries;
import com.google.firebase.auth.FirebaseAuth;
import com.squareup.picasso.Picasso;

import java.util.Locale;

public class HomeActivity extends AppCompatActivity implements AbsListView.OnScrollListener {
    public static final String INTENT_FLAG = "flag";
    public static final int FIRST_ENTER = 1;
    //public static final int REBUILD = 2;
    public static final int RECOMMENDATION_ENTER = 2;
    ExpandableListView list;
    EditText searchEt;
    ProgressBar progressBar;
    HomeActivity context;
    ImageView questionmarkHomeBtn;
    boolean isInSearchMode;
    boolean isInRecommendationMode;
    TextView homeToolbarTitleTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        loadLocale();
        Toolbar toolbar = findViewById(R.id.homeToolbar);
        toolbar.setTitle("");
        homeToolbarTitleTV = findViewById(R.id.home_titleTV);
        setSupportActionBar(toolbar);
        context = this;
        isInSearchMode = false;
        isInRecommendationMode = false;
        progressBar = findViewById(R.id.home_progressbar);
        questionmarkHomeBtn = findViewById(R.id.home_questionmark_btn);
        list = findViewById(R.id.home_series_list);
        searchEt = findViewById(R.id.home_search_et);
        progressBar.setVisibility(View.VISIBLE);
        TvSeriesHomeList.getInstance().clear();
        TvSeriesFavoriteList.getInstance().clear();
        TvSeriesFavoriteList.getInstance().initializeSeriesList();
        UsersBookmarks.getInstance().initializeBookmarks();
        Bundle b = getIntent().getExtras();
        int flag = 1;
        if (b != null) flag = b.getInt(INTENT_FLAG);
        if (flag == FIRST_ENTER) {
            new FillSeriesListFromFireBaseTask(this, list).execute();
        } else if (flag == RECOMMENDATION_ENTER) {
            progressBar.setVisibility(View.VISIBLE);
            isInRecommendationMode = true;
            homeToolbarTitleTV.setText(getString(R.string.recommendation));
            new FillSeriesListFromFireBaseBySuggestionsTask(context, list).execute();
        }
        list.setOnScrollListener(this);
        list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                TvSeriesFavoriteList favorites = TvSeriesFavoriteList.getInstance();
                TvSeries series = TvSeriesHomeList.getInstance().getSeries().get(position);
                if (favorites.contains(series.getId())) {
                    favorites.remove(series.getId());
                    ImageView star = view.findViewById(R.id.series_list_fav_iv);
                    Picasso.get().load(R.drawable.emptystar).fit().into(star);
                    Toast.makeText(getApplicationContext(), "Removed from favorites", Toast.LENGTH_SHORT).show();
                } else if (favorites.canAdd(series)) {
                    favorites.add(series);
                    ImageView star = view.findViewById(R.id.series_list_fav_iv);
                    Picasso.get().load(R.drawable.filledstar).fit().into(star);
                    Toast.makeText(getApplicationContext(), "Added to favorites", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Maximum of 5 series can be added to favorites", Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });
        searchEt.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                String searchString = s.toString().trim();
                if (searchString.isEmpty()) {
                    isInSearchMode = false;
                    TvSeriesHomeList.getInstance().clear();
                    new FillSeriesListFromFireBaseTask(context, list).execute();
                } else {
                    isInSearchMode = true;
                    new FillSeriesListFromFireBaseBySearchTask(context, list, searchString).execute();
                }
            }
        });
        questionmarkHomeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder builder  = new AlertDialog.Builder(HomeActivity.this);
                builder.setCancelable(true);
                builder.setTitle(getString(R.string.how_to_use));
                builder.setMessage(getString(R.string.home_fav_bookmark_explain));
                builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.cancel();
                    }
                });
                builder.show();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        loadLocale();
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (!isInSearchMode && !isInRecommendationMode) {
            switch (view.getId()) {
                case R.id.home_series_list:

                    final int lastItem = firstVisibleItem + visibleItemCount;

                    if (lastItem == totalItemCount) {
                        if (TvSeriesHomeList.getInstance().getPreLast() != lastItem) {
                            TvSeriesHomeList.getInstance().incrementPage();
                            new FillSeriesListFromFireBaseTask(this, list).execute();
                            TvSeriesHomeList.getInstance().setPreLast(lastItem);
                        }
                    }
            }
        }
    }


    public ProgressBar getProgressBar() {
        return progressBar;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.profilemenu:
                startActivity(new Intent(this, ProfileActivity.class));
                break;
            case R.id.favoritesmenu:
                startActivity(new Intent(this, FavoritesActivity.class));
                break;
            case R.id.aboutmenu:
                startActivity(new Intent(this, AboutActivity.class));
                break;
            case R.id.signoutmenu:
                FirebaseAuth.getInstance().signOut();
                Intent intent = new Intent(this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
                break;
            case R.id.recommendationmenu:
                TvSeriesHomeList.getInstance().clear();
                progressBar.setVisibility(View.VISIBLE);
                isInRecommendationMode = true;
                new FillSeriesListFromFireBaseBySuggestionsTask(context, list).execute();
                homeToolbarTitleTV.setText(getString(R.string.recommendation));
                break;
            case R.id.homemenu:
                if (isInRecommendationMode) {
                    isInRecommendationMode = false;
                    TvSeriesHomeList.getInstance().clear();
                    new FillSeriesListFromFireBaseTask(this, list).execute();
                }
                homeToolbarTitleTV.setText(getString(R.string.home));
                break;
            case R.id.rateusmenu:
                try{
                    startActivity(new Intent(Intent.ACTION_VIEW,
                            Uri.parse("market://details?id=com.idan.idanzimbler.epiclogin")));
                }catch (ActivityNotFoundException e){
                    startActivity(new Intent(Intent.ACTION_VIEW,
                            Uri.parse("https://play.google.com/store/apps/details?id=com.idan.idanzimbler.epiclogin")));
                }
        }
        return true;
    }

    @Override
    public void onBackPressed() {
        if (!searchEt.getText().toString().isEmpty()) {
            searchEt.setText("");
        } else if (isInRecommendationMode) {
            isInRecommendationMode = false;
            TvSeriesHomeList.getInstance().clear();
            new FillSeriesListFromFireBaseTask(this, list).execute();
        }else {
            super.onBackPressed();
        }
    }
    public void setLocale(String lang) {
        Locale locale = new Locale(lang,"US");
        if(lang.equals("he")){
            locale = new Locale(lang,"IL");
        }
        else if(lang.equals("ar")){
            locale = new Locale(lang,"JO");
        }
        Locale.setDefault(locale);
        Configuration config = new Configuration();
        config.locale = locale;
        getBaseContext().getResources().updateConfiguration(config,getBaseContext().getResources().getDisplayMetrics());
        SharedPreferences.Editor editor = getSharedPreferences("Settings" ,MODE_PRIVATE).edit();
        editor.putString("My_Lang",lang);
        editor.apply();
    }
    public void loadLocale(){
        SharedPreferences prefs = getSharedPreferences("Settings",Activity.MODE_PRIVATE);
        String language = prefs.getString("My_Lang", "");
        setLocale(language);
    }
}

The XML file:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".view.HomeActivity">

    <EditText
        android:id="@+id/home_search_et"
        android:layout_width="301dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="14dp"
        android:layout_weight="1"
        android:ems="10"
        android:hint="@string/enter_tv_series_name"
        android:inputType="textPersonName"
        app:backgroundTint="@color/common_google_signin_btn_text_dark_focused"
        app:layout_constraintBottom_toTopOf="@+id/home_series_list"
        app:layout_constraintEnd_toStartOf="@+id/home_questionmark_btn"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
         />

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:layout_constraintBottom_toTopOf="@+id/home_search_et"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/homeToolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:contentInsetStart="0dp"
            android:contentInsetLeft="0dp"
            android:contentInsetEnd="0dp"
            android:contentInsetRight="0dp"
            android:elevation="2dp"
            android:gravity="end"
            app:contentInsetEnd="0dp"
            app:contentInsetLeft="0dp"
            app:contentInsetRight="0dp"
            app:contentInsetStart="0dp"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            tools:targetApi="lollipop">

            <TextView
                android:id="@+id/home_titleTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="@string/home"
                android:textColor="@color/common_google_signin_btn_text_dark_default"
                android:textSize="25sp"
                android:textStyle="bold" />
        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>

    <ExpandableListView
        android:id="@+id/home_series_list"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="4dp"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/home_search_et" />

    <ProgressBar
        android:id="@+id/home_progressbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:indeterminateDrawable="@drawable/blackprogressbar"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@+id/home_series_list"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/home_questionmark_btn"
        android:layout_width="34dp"
        android:layout_height="24dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/home_search_et"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/home_search_et"
        app:srcCompat="@drawable/questionmarklogo"
        android:contentDescription="TODO" />

</android.support.constraint.ConstraintLayout>

the Run:

V/FA: Activity paused, time: 2504321
V/FA: onActivityCreated
D/FA: Logging event (FE): user_engagement(_e), Bundle[{firebase_event_origin(_o)=auto, engagement_time_msec(_et)=11068, firebase_screen_class(_sc)=MainActivity, firebase_screen_id(_si)=-8684354233398184439}]
W/dalvikvm: JNI WARNING: NewStringUTF input is not valid Modified UTF-8: illegal start byte 0xf0
             string: 'en_Latn_US_�_US'
             in Llibcore/icu/ICU;.addLikelySubtags:(Ljava/lang/String;)Ljava/lang/String; (NewStringUTF)
I/dalvikvm: "main" prio=5 tid=1 NATIVE
      | group="main" sCount=0 dsCount=0 obj=0xa4d56bd8 self=0xb7e34eb0
      | sysTid=3387 nice=0 sched=0/0 cgrp=apps handle=-1216573376
      | state=R schedstat=( 1431490769 212065377 2672 ) utm=91 stm=51 core=1
I/dalvikvm:   #00  pc 000bd936  /system/lib/libdvm.so (dvmDumpNativeStack(DebugOutputTarget const*, int)+86)
      #01  pc 00098513  /system/lib/libdvm.so (dvmDumpThreadEx(DebugOutputTarget const*, Thread*, bool)+1155)
      #02  pc 00098806  /system/lib/libdvm.so (dvmDumpThread(Thread*, bool)+86)
      #03  pc 0004d3ff  /system/lib/libdvm.so (ScopedCheck::checkUtfString(char const*, bool)+271)
      #04  pc 0004e2ad  /system/lib/libdvm.so (ScopedCheck::check(bool, char const*, ...)+1437)
      #05  pc 00052927  /system/lib/libdvm.so
      #06  pc 000204be  /system/lib/libjavacore.so
      #07  pc 0002a4ab  /system/lib/libdvm.so (dvmPlatformInvoke+79)
    at libcore.icu.ICU.addLikelySubtags(Native Method)
I/dalvikvm:     at android.text.TextUtils.getLayoutDirectionFromLocale(TextUtils.java:1740)
    at android.content.res.Configuration.setLayoutDirection(Configuration.java:1295)
    at android.content.res.Configuration.updateFrom(Configuration.java:820)
    at android.content.res.Resources.updateConfiguration(Resources.java:1557)
    at android.content.res.Resources.updateConfiguration(Resources.java:1511)
    at android.support.v7.widget.ResourcesWrapper.updateConfiguration(ResourcesWrapper.java:232)
    at android.content.res.Resources.<init>(Resources.java:202)
    at android.content.res.Resources.<init>(Resources.java:179)
    at android.support.v7.widget.ResourcesWrapper.<init>(ResourcesWrapper.java:48)
    at android.support.v7.widget.TintResources.<init>(TintResources.java:35)
    at android.support.v7.widget.TintContextWrapper.<init>(TintContextWrapper.java:101)
    at android.support.v7.widget.TintContextWrapper.wrap(TintContextWrapper.java:69)
    at android.support.v7.widget.AppCompatEditText.<init>(AppCompatEditText.java:69)
    at android.support.v7.widget.AppCompatEditText.<init>(AppCompatEditText.java:65)
    at android.support.v7.app.AppCompatViewInflater.createEditText(AppCompatViewInflater.java:192)
    at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:114)
    at android.support.v7.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1266)
    at android.support.v7.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1316)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:684)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
    at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
    at com.idan.idanzimbler.epiclogin.view.HomeActivity.onCreate(HomeActivity.java:58)
    at android.app.Activity.performCreate(Activity.java:5231)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
    at android.app.ActivityThread.access$800(ActivityThread.java:135)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5001)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
    at dalvik.system.NativeStart.main(Native Method)
E/dalvikvm: VM aborting
A/libc: Fatal signal 6 (SIGABRT) at 0x00000d3b (code=-6), thread 3387 (mbler.
Application terminated. 

Upvotes: 1

Views: 671

Answers (1)

Julien Arzul
Julien Arzul

Reputation: 971

The stacktrace seems to indicate an issue reading the current Resources Configuration (whether your Locale is RTL or not).

Looking at the activity code, you are modifying the Locale used by your application instead of using the phone Locale which would explain the issue. Your Activity will actually go through onCreate twice. The first time is probably inflating your XML view without any trouble but once you set the new Configuration (by calling loadLocale()), the Activity will be destroyed and re-created, which will execute onCreate() a second time with your new Configuration. This is when your application is crashing.

In my opinion, the problem is most likely in the setLocale() method, the change of Configuration is not done correctly and new APIs are able to use a default value whereas older APIs simply crash.

Even though I wouldn't recommend modifying the Locale in the app, here is more information on modifying it in an Android application:
https://proandroiddev.com/change-language-programmatically-at-runtime-on-android-5e6bc15c758

There is different methods to use depending on the version of the APIs you support.

The method he is using to change the configuration looks like:

    private static Context updateResources(Context context, Locale locale) {
        Locale.setDefault(locale);

        Resources res = context.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT >= 17) {
            config.setLocale(locale);
            context = context.createConfigurationContext(config);
        } else {
            config.locale = locale;
            res.updateConfiguration(config, res.getDisplayMetrics());
        }
        return context;
    }

Upvotes: 2

Related Questions