AppIntro icon indicating copy to clipboard operation
AppIntro copied to clipboard

OutOfMemoryError

Open yoiyang opened this issue 7 years ago • 8 comments

Version of AppIntro: implementation 'com.github.apl-devs:appintro:v4.2.3'

Phone info: Samsung

  • Model: SM-S327VL
  • Orientation: Portrait
  • RAM free: 209.15 MB
  • Disk free: 4.17 GB

Operating system:

  • Version: 6.0.1
  • Orientation: Portrait
  • Rooted: No

This line was emphasized indicating the cause of error: com.github.paolorotolo.appintro.AppIntroBaseFragment.onCreateView (AppIntroBaseFragment.java:103)

Fatal Exception: java.lang.OutOfMemoryError
Failed to allocate a 23950092 byte allocation with 16777216 free bytes and 21MB until OOM com.github.paolorotolo.appintro.AppIntroBaseFragment.onCreateView

The complete Log:

android.graphics.BitmapFactory.nativeDecodeAsset (BitmapFactory.java)
android.graphics.BitmapFactory.decodeStream (BitmapFactory.java:856)
android.graphics.BitmapFactory.decodeResourceStream (BitmapFactory.java:675)
android.graphics.drawable.Drawable.createFromResourceStream (Drawable.java:2230)
android.content.res.Resources.loadDrawableForCookie (Resources.java:4282)
android.content.res.Resources.loadDrawable (Resources.java:4156)
android.content.res.Resources.getDrawable (Resources.java:2045)
android.content.res.Resources.getDrawable (Resources.java:2027)
android.content.Context.getDrawable (Context.java:464)
android.support.v4.content.ContextCompat.getDrawable (ContextCompat.java:358)
android.support.v7.widget.AppCompatDrawableManager.getDrawable (AppCompatDrawableManager.java:198)
android.support.v7.widget.AppCompatDrawableManager.getDrawable (AppCompatDrawableManager.java:186)
android.support.v7.content.res.AppCompatResources.getDrawable (AppCompatResources.java:100)
android.support.v7.widget.AppCompatImageHelper.setImageResource (AppCompatImageHelper.java:85)
android.support.v7.widget.AppCompatImageView.setImageResource (AppCompatImageView.java:93)
com.github.paolorotolo.appintro.AppIntroBaseFragment.onCreateView (AppIntroBaseFragment.java:103)
android.support.v4.app.Fragment.performCreateView (Fragment.java:2346)
android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManager.java:1428)
android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState (FragmentManager.java:1759)
android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManager.java:1827)
android.support.v4.app.BackStackRecord.executeOps (BackStackRecord.java:797)
android.support.v4.app.FragmentManagerImpl.executeOps (FragmentManager.java:2596)
android.support.v4.app.FragmentManagerImpl.executeOpsTogether (FragmentManager.java:2383)
android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute (FragmentManager.java:2338)
android.support.v4.app.FragmentManagerImpl.execSingleAction (FragmentManager.java:2215)
android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss (BackStackRecord.java:649)
android.support.v4.app.FragmentPagerAdapter.finishUpdate (FragmentPagerAdapter.java:145)
android.support.v4.view.ViewPager.populate (ViewPager.java:1238)
android.support.v4.view.ViewPager.populate (ViewPager.java:1086)
android.support.v4.view.ViewPager$3.run (ViewPager.java:267)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:911)
android.view.Choreographer.doCallbacks (Choreographer.java:686)
android.view.Choreographer.doFrame (Choreographer.java:619)
android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:897)
android.os.Handler.handleCallback (Handler.java:739)
android.os.Handler.dispatchMessage (Handler.java:95)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:7422)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)```

I use AppIntro in the most standard way: 
    SliderPage sliderPage1 = new SliderPage();
    sliderPage1.setTitle("Welcome!");
    sliderPage1.setDescription("Here's a quick intro.");
    sliderPage1.setImageDrawable(R.drawable.icon1);
    sliderPage1.setBgColor(Color.TRANSPARENT);
    addSlide(AppIntroFragment.newInstance(sliderPage1));
   addSlide(AppIntroFragment.newInstance("Welcome", "Enjoy", R.drawable.icon1, R.drawable.gradient));

yoiyang avatar Jul 20 '18 01:07 yoiyang

Do you have a sample project or some code to share to reproduce this?

cortinico avatar Jul 20 '18 08:07 cortinico

Yes. I gave a snippet of the code above, and here's the entire code (with some repetition of the snippet).

public class IntroActivity extends AppIntro {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // I added this try/catch block to avoid another OutOfMemoryError cras
        try {
            setDoneText("Log In");
            setSkipText("Skip to Log In");

            SliderPage sliderPage1 = new SliderPage();
            sliderPage1.setTitle("Welcome!");
            sliderPage1.setDescription("Here's a quick intro about FridgeMate.");
            sliderPage1.setImageDrawable(R.drawable.icon1);
            sliderPage1.setBgColor(Color.TRANSPARENT);
            addSlide(AppIntroFragment.newInstance(sliderPage1));

            SliderPage sliderPage2 = new SliderPage();
            sliderPage2.setTitle("Content List");
            sliderPage2.setDescription("Every thing in your fridge at a glance.");
            sliderPage2.setImageDrawable(R.drawable.intro1);
            sliderPage2.setBgColor(Color.TRANSPARENT);
            addSlide(AppIntroFragment.newInstance(sliderPage2));

            SliderPage sliderPage3 = new SliderPage();
            sliderPage3.setTitle("Put stuff in your fridge");
            sliderPage3.setDescription("Simply by clicking the + Button.\n Try Quick Add, it scans! \n");
            sliderPage3.setImageDrawable(R.drawable.intro2);
            sliderPage3.setBgColor(Color.TRANSPARENT);
            addSlide(AppIntroFragment.newInstance(sliderPage3));

            SliderPage sliderPage4 = new SliderPage();
            sliderPage4.setTitle("Need cooking advice? \nSure!");
            sliderPage4.setDescription("FridgeMate recommends you recipes based on what you have in your fridge");
            sliderPage4.setImageDrawable(R.drawable.intro3);
            sliderPage4.setBgColor(Color.TRANSPARENT);
            addSlide(AppIntroFragment.newInstance(sliderPage4));

            SliderPage sliderPage5 = new SliderPage();
            sliderPage5.setTitleTypeface("casual");
            sliderPage5.setTitle("Fridge? Friends?");
            sliderPage5.setDescription("Invite friends to your \"fridge family\". \n Connect with people and their foods.");
            sliderPage5.setImageDrawable(R.drawable.intro4);
            sliderPage5.setBgColor(Color.TRANSPARENT);
            addSlide(AppIntroFragment.newInstance(sliderPage5));

            SliderPage sliderPage6 = new SliderPage();
            sliderPage6.setTitleTypeface("casual");
            sliderPage6.setTitle("Need a reminder about what to buy?");
            sliderPage6.setDescription("Of course, here's your shopping list.");
            sliderPage6.setImageDrawable(R.drawable.intro5);
            sliderPage6.setBgColor(Color.TRANSPARENT);
            addSlide(AppIntroFragment.newInstance(sliderPage6));

            // Instead of fragments, you can also use our default slide
            // Just set a title, description, background and image. AppIntro will do the rest.
            addSlide(AppIntroFragment.newInstance("Welcome to FridgeMate.", "Enjoy! - C.O.O.L", R.drawable.icon1, R.drawable.animation_gradient));

            // Hide Skip/Done button.
            showSkipButton(true);
            setProgressButtonEnabled(true);
        }
        catch(OutOfMemoryError e){
            Intent i = new Intent(getApplicationContext(), LoginActivity.class);
            startActivity(i);
            setResult(CLOSE_ALL);
            finish();
            return;
        }
    }

    final int CLOSE_ALL = 23333;

    @Override
    public void onSkipPressed(Fragment currentFragment) {
        super.onSkipPressed(currentFragment);
        Intent i = new Intent(getApplicationContext(), LoginActivity.class);
        startActivity(i);
        setResult(CLOSE_ALL);
        finish();
    }

    @Override
    public void onDonePressed(Fragment currentFragment) {
        super.onDonePressed(currentFragment);
        Intent i = new Intent(getApplicationContext(), LoginActivity.class);
        startActivity(i);
        setResult(CLOSE_ALL);
        finish();
    }

    @Override
    public void onSlideChanged(@Nullable Fragment oldFragment, @Nullable Fragment newFragment) {
        super.onSlideChanged(oldFragment, newFragment);
    }
}

yoiyang avatar Jul 20 '18 19:07 yoiyang

was this issue resolved?

damionx7 avatar Aug 04 '18 05:08 damionx7

No, the issue wasn't solved. I'm sorry for mis-pressing the Close button. In addition, with the exact same code I provided above, it has led many same crashes happened on Asus (Zenfone), Samsung(Galaxy S5, Galaxy J3), Huawei (P9 lite), LGE (Nexus), and two other brands. Let me know if there's more info I can find to help you resolve it!

yoiyang avatar Aug 04 '18 05:08 yoiyang

Hey @YoiYang

Looks like the problem is with the assets you're using. The app is trying to allocate 23Mb, so can I ask you to check the size of:

R.drawable.intro1
R.drawable.intro2
R.drawable.intro3
R.drawable.intro4
R.drawable.icon1
R.drawable.animation_gradient

Furthermore, if you could provide a branch/fork would be better for debugging/profiling.

cortinico avatar Aug 06 '18 13:08 cortinico

As I double checked the sizes of these files, they sum up to less than 400kb. For the recent versions of my app, I didn't use R.drawable.animation_gradient. But errors continue to occur on different Android phone platforms (LGE, LYF, Prestigio, Xiaomi, Samsung) from Android 4 to Android 7.

Here's a hyperlink to the file where I use the AppIntro: https://github.com/htoo97/FridgeMate-mobile/blob/master/app/src/main/java/com/fridgemate/yangliu/fridgemate/IntroActivity.java

As a sidenote, my app's compiled and target sdk version is 27; its minimum sdk version is 21.

yoiyang avatar Oct 20 '18 01:10 yoiyang

This is a known issue for devices with lower resolutions. You should scale down your images so the device doesn't have to do it at runtime. See here for more: https://github.com/paolorotolo/AppIntro/issues/402#issuecomment-439701856

TomTasche avatar Nov 18 '18 15:11 TomTasche

Hey @paolorotolo Do you think using fragmentpageradapter/fragmentstatepageradapter in appintrobase could potentially solve this issue(From what I read, one destroys the view hierarchy and another destroys the whole fragment if not in view that could potentially save memory)

AnuthaDev avatar Feb 23 '19 02:02 AnuthaDev