Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android App crashes after being idle for a long time

I'm currently facing something which is really weird with my cell phone. If I use the app I'm developing I have no problems, until I stop using it for a long time (when this happens the instance of the app gets closed I believe). I downloaded an app which "fills your RAM" in order to emulate this behavior. What I don't understand is the error: Every time I try using the app after I've filled the RAM I get a ResourceNotFound exception, which doesn't make sense to me, at least. As you can see by the trace, the error is in the following line:

mView = inflater.inflate(mLayout,container, false);

Here's the trace:

11-25 08:22:09.496: E/AndroidRuntime(6386): FATAL EXCEPTION: main
11-25 08:22:09.496: E/AndroidRuntime(6386): Process: com.papinotas, PID: 6386
11-25 08:22:09.496: E/AndroidRuntime(6386): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.papinotas/com.papinotas.views.activities.TeacherMainActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x0
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.ActivityThread.access$900(ActivityThread.java:161)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.os.Handler.dispatchMessage(Handler.java:102)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.os.Looper.loop(Looper.java:157)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.ActivityThread.main(ActivityThread.java:5356)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at java.lang.reflect.Method.invokeNative(Native Method)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at java.lang.reflect.Method.invoke(Method.java:515)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at dalvik.system.NativeStart.main(Native Method)
11-25 08:22:09.496: E/AndroidRuntime(6386): Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.content.res.Resources.getValue(Resources.java:2036)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.content.res.Resources.loadXmlResourceParser(Resources.java:3265)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.content.res.Resources.getLayout(Resources.java:1852)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at com.androidinit.base.PlaceHolderFragment.onCreateView(PlaceHolderFragment.java:29)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.Fragment.performCreateView(Fragment.java:1700)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1044)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1853)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.Activity.performCreate(Activity.java:5429)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
11-25 08:22:09.496: E/AndroidRuntime(6386):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
11-25 08:22:09.496: E/AndroidRuntime(6386):     ... 11 more
11-25 08:22:09.506: W/ActivityManager(847):   Force finishing activity com.papinotas/.views.activities.TeacherMainActivity
11-25 08:22:09.516: W/ContextImpl(847): Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:1479 com.android.server.am.ActivityStack.startPausingLocked:1006 com.android.server.am.ActivityStack.finishActivityLocked:3162 com.android.server.am.ActivityStack.finishTopRunningActivityLocked:3005 com.android.server.am.ActivityStackSupervisor.finishTopRunningActivityLocked:3142 
11-25 08:22:09.526: D/CrashAnrDetector(847): processName: com.papinotas
11-25 08:22:09.526: D/CrashAnrDetector(847): broadcastEvent : com.papinotas data_app_crash
11-25 08:22:09.526: V/SmartFaceService - 3rd party pause(847): onReceive [android.intent.action.ACTIVITY_STATE/com.papinotas/pause]
11-25 08:22:09.526: W/ContextImpl(847): Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:1479 com.android.server.analytics.data.collection.application.CrashAnrDetector.broadcastEvent:296 com.android.server.analytics.data.collection.application.CrashAnrDetector.processDropBoxEntry:254 com.android.server.analytics.data.collection.application.CrashAnrDetector.access$100:60 com.android.server.analytics.data.collection.application.CrashAnrDetector$1.onReceive:102 

Here's the complete class of the trace:

package com.androidinit.base;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

    public class PlaceHolderFragment extends Fragment {

    private int mLayout;
    private View mView;
    private BaseActivity mActivity;

    public PlaceHolderFragment() {
    }

    public PlaceHolderFragment(int mLayout, BaseActivity mActivity) {

        this.mLayout = mLayout;
        this.mActivity = mActivity;

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

            mView = inflater.inflate(mLayout,container, false);
            mActivity.setActivityView(mView);

        return mView;
    }

}

Also, here's the methods I believe might be important in BaseActivity, which I use to create all my activities (all my activities extend BaseActivity)

public class BaseActivity extends Activity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        session = new SessionManager(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ai_base_activity);
        mNavigationDrawerFragment = (NavigationDrawerFragment)
                getFragmentManager().findFragmentById(R.id.navigation_drawer);
        mTitle = getTitle();

        // Set up the drawer.
        mNavigationDrawerFragment.setUp(
                R.id.navigation_drawer,
                (DrawerLayout) findViewById(R.id.drawer_layout));
    }
    @Override
    public void onResume(){
        super.onResume();
        setSpinner();
    }
    public void createFragmentView(int layoutId) {

        //FIXME agregar la clase hija
        mFragment = new PlaceHolderFragment(layoutId, this);
        getFragmentManager().beginTransaction().add(R.id.container, mFragment).commit();
    }

    public PlaceHolderFragment getPlaceHolderFragment( ) {
        return mFragment;
    }
}

I haven't found any solutions to this problem, which is occurring in my Galaxy S4, Android 4.4.3. Any help would be greatly appreciated.

like image 852
Waclock Avatar asked Nov 25 '14 13:11

Waclock


People also ask

Why does my app keep crashing on Android?

If your Android apps keep crashing or freezing it's usually because you're low on space or running too many apps at once. Other reasons for crashing apps include a spotty Wi-Fi connection or an old version of the app that hasn't been updated.

Why does my app keep closing for no reason?

Apps on Android can crash because of low storage space, too many apps running simultaneously, a weak internet connection, or not having the proper app updates installed.

What to do if an app continuously crashes?

To fix Android apps that keep crashing: To do this, go to Settings and open Apps. Under Your apps, you'll see a list of the apps currently installed on your device. From the list, tap the app that keeps crashing and tap Force stop in the bottom right corner. Then try opening the app again.


2 Answers

You are getting a ResourceNotFoundException because you are requesting to load a resource with an ID of 0.

You are requesting to load a resource with an ID of 0 because mLayout is 0.

mLayout is 0 because it is a data member of your fragment, and your fragment is being recreated, probably because your process was terminated while you were in the background.

Frankly, IMHO, passing in a layout ID to a fragment is a code smell, and passing in BaseActivity is a flat-out bug in your code. If your fragment needs an activity, call getActivity() on the fragment. Delete the two-parameter constructor entirely.

Assuming that there is actually a legitimate reason to pass in a layout ID, use the factory method pattern and the arguments Bundle, instead of your two-argument constructor. The arguments Bundle is automatically saved as part of the instance state of your fragment, and therefore it will not be lost when your process is terminated and later re-created.

I use the factory method/arguments Bundle pattern in this sample project, so that the fragment knows what page of the ViewPager it is. That position is stored in the arguments Bundle and is retrieved from that Bundle when the fragment needs it:

/***
  Copyright (c) 2012-14 CommonsWare, LLC
  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.

  From _The Busy Coder's Guide to Android Development_
    http://commonsware.com/Android
 */

package com.commonsware.android.pager;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

public class EditorFragment extends Fragment {
  private static final String KEY_POSITION="position";

  static EditorFragment newInstance(int position) {
    EditorFragment frag=new EditorFragment();
    Bundle args=new Bundle();

    args.putInt(KEY_POSITION, position);
    frag.setArguments(args);

    return(frag);
  }

  @Override
  public View onCreateView(LayoutInflater inflater,
                           ViewGroup container,
                           Bundle savedInstanceState) {
    View result=inflater.inflate(R.layout.editor, container, false);
    EditText editor=(EditText)result.findViewById(R.id.editor);
    int position=getArguments().getInt(KEY_POSITION, -1);

    editor.setHint(String.format(getString(R.string.hint), position + 1));

    return(result);
  }
}
like image 61
CommonsWare Avatar answered Sep 27 '22 18:09

CommonsWare


Your mLayout gets it's default value which is 0 when the Fragment is destroyed and recreated. That happens when you, lets say, change application to that RAM filling app and come back to your app.

So what you need to do is use onSavedInstanceState method and store your needed variables in there. When onCreateView gets called and the parameter savedInstanceState isn't null, you have to retrieve the variables from Bundle.

Read this to understand what I am trying to say: onSavedInstanceState method

and it would look like this then:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    if (savedInstanceState != null) {
        mLayout = savedInstanceState.getInt("layout_id");
    }

    mView = inflater.inflate(mLayout,container, false);
    // Return the Activity this fragment is currently associated with.
    BaseActivity activity = (BaseActivity) getActivity();
    activity.setActivityView(mView);

    return mView;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putInt("layout_id", mLayout);
    super.onSaveInstanceState(outState);
}
like image 20
vilpe89 Avatar answered Sep 27 '22 18:09

vilpe89