1

I'm implementing an application playing video. There are 2 activities: MainMenuActivity (in portrait mode) and VideoPlayerActivity(can rotate) . MainMenuActivity has HomeFragmentLT fragment. In HomeFragmentLT fragment there are a ViewPager. Here is my HomeFragmentLT and ViewPager(HomePager):

public class HomeFragmentLT extends Fragment implements Observer
{
    public static String TAG = "HomeFragmentLT";
    private ViewGroup mLayout;
    private View mHeader;
    private HomeAdapter mHomeAdapter;       
@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    Log.e(TAG, "onCreate");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    if (mLayout == null)        
        mLayout = (ViewGroup) inflater.inflate(R.layout.home_listview, null);       
    else        
        ((ViewGroup) mLayout.getParent()).removeView(mLayout);      
    initViews();        
    return mLayout;
}

public HomeFragmentLT(){}

private void initViews()
{       
    mPager = (ViewPager) mHeader.findViewById(R.id.home_pager);
    .......
    .......
}

@Override
public void onStart()
{
    super.onStart();
    if (!mDataReceived)
        getData();      
    Log.e(TAG, "onStart");
}

@Override
public void onStop()
{
    DataHelper.getInstance().deleteObserver(this);
    super.onStop();
    Log.e(TAG, "onStop");
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    Log.e(TAG, "onDestroy");
}

private void getData()
{
    if (mError)
    {
        UIUtils.toggleError(mLayout, false, null);
        mListView.setOnTouchListener(null);
        UIUtils.toggleLoading(mLayout, true);
    }
    DataHelper.getInstance().addObserver(this);
    DataHelper.getInstance().getHomeData();
}

private void setData()
{
    mHomeAdapter = new HomeAdapter(getActivity(), mPager, mHomeData.getHotPrograms());
    mPager.setAdapter(mHomeAdapter);
    mIndicator.setViewPager(mPager);

    .............
}

@Override
public void update(Observable observable, Object data)
{
    if (data == null)
        return;
    Result result = (Result) data;
    if (Method.GET_HOME_DATA.equals(result.getParams().getMethod()))
    {
        if (result.getError() == null)
        {
            mHomeData = (HomeObj) result.getData();
            setData();
            mDataReceived = true;
            mError = false;
            DataHelper.getInstance().deleteObserver(this);
        }           
    }
}
......................
public static class HomeAdapter extends PagerAdapter
{
    private List<Program> mPrograms;
    private View[] mViews;
    private Context mContext;

    public HomeAdapter(Context context, ViewPager viewpager, List<Program> programs){...........}

    @Override
    public int getCount()
    {
        return mPrograms.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object)
    {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position)
    {
        View view;
        if ((view = mViews[position]) != null)
        {
            ImageView img = (ImageView) view.findViewById(R.id.img);
            if (img.getDrawable() == null)
            {
                UIUtils.toggleLoading(view, true);
                ImageManager.getInstance().push(mPrograms.get(position).getThumbnail(), img, mLoadingListener);
            }
            return view;
        }

        view = LayoutInflater.from(mContext).inflate(R.layout.home_program_item_top, null);
        view.setTag(mPrograms.get(position).getId());
        view.setLayoutParams(mParams);
        if (Constants.MAY_CUI_DETECTED)
            ImageManager.getInstance().push(mPrograms.get(position).getThumbnail(),
                    (ImageView) view.findViewById(R.id.img), mParams.width, mParams.height, mLoadingListener);
        else
            ImageManager.getInstance().push(mPrograms.get(position).getThumbnail(),
                    (ImageView) view.findViewById(R.id.img), mLoadingListener);

        view.setOnClickListener(mOnItemClick);
        container.addView(view);
        return mViews[position] = view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object){}
}   
}

In MainMenuActivity, I add HomeFragmentLT in onCreate()

getSupportFragmentManager().beginTransaction().add(R.id.dummy, mHomeFragment).commitAllowingStateLoss();
getSupportFragmentManager().executePendingTransactions();

Everything works fine. But when I put the phone in landscape, then start VideoPlayerActivity(means VideoPlayerActivity in landscape mode) to play video from MainMenuActivity(portrait) and press Back Button immediately. It got exception. Here is my logcat:

12-09 18:30:09.102: E/MainMenuActivity(23287): onCreate()
12-09 18:30:09.332: E/MainMenuActivity(23287): onStart()
12-09 18:30:09.432: E/MainMenuActivity(23287): onResume()
12-09 18:30:09.703: E/HomeFragmentLT(23287): onCreate()
12-09 18:30:09.703: E/HomeFragmentLT(23287): onCreateView()
...........
12-09 18:30:14.487: E/MainMenuActivity(23287): onPause()
12-09 18:30:14.788: E/VideoPlayerActivity(23287): onCreate()
12-09 18:30:14.788: E/VideoPlayerActivity(23287): onStart()
...........
12-09 18:30:15.418: E/VideoPlayerActivity(23287): onPause()
12-09 18:30:15.588: E/HomeFragmentLT(23287): onStop()
12-09 18:30:15.639: E/MainMenuActivity(23287): onDestroy()
12-09 18:30:15.659: E/MainMenuActivity(23287): onCreate()
12-09 18:30:15.659: E/HomeFragmentLT(23287): onCreate()
12-09 18:30:15.719: E/MainMenuActivity(23287): onStart()
12-09 18:30:15.789: E/HomeFragmentLT(23287): onCreateView()
12-09 18:30:15.979: E/MainMenuActivity(23287): onResume()
12-09 18:30:16.169: E/MainMenuActivity(23287): onPause()
12-09 18:30:16.169: E/HomeFragmentLT(23287): onStop()
12-09 18:30:16.179: E/MainMenuActivity(23287): onDestroy()
12-09 18:30:16.199: E/MainMenuActivity(23287): onCreate()
12-09 18:30:16.199: E/HomeFragmentLT(23287): onCreate()
12-09 18:30:16.239: E/MainMenuActivity(23287): onStart()
12-09 18:30:16.259: E/HomeFragmentLT(23287): onCreateView()
12-09 18:30:16.379: E/MainMenuActivity(23287): onResume()
12-09 18:30:16.469: E/AndroidRuntime(23287): FATAL EXCEPTION: main
12-09 18:30:16.469: E/AndroidRuntime(23287): java.lang.IllegalStateException: Activity has been destroyed
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1358)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at com.vng.zingtv.activity.MainMenuActivity$3.run(MainMenuActivity.java:375)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.os.Handler.handleCallback(Handler.java:615)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.os.Handler.dispatchMessage(Handler.java:92)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.os.Looper.loop(Looper.java:137)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at android.app.ActivityThread.main(ActivityThread.java:4744)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at java.lang.reflect.Method.invokeNative(Native Method)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at java.lang.reflect.Method.invoke(Method.java:511)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
12-09 18:30:16.469: E/AndroidRuntime(23287):    at dalvik.system.NativeStart.main(Native Method)

There are 2 issues I need your help.
1. Why the MainMenuActivity is destroyed and recreated again? (my LogCat)
2. What's wrong in my HomeFragmentLTfragment that causes IllegalStateException?

Thanks in advance.

EDIT
I want my VideoPlayerActivity to be rotated according to device orientation. So in manifiest.xml

<activity
     android:name=".activity.VideoPlayerActivity"
     android:screenOrientation="portrait" />

and in onCreate() of VideoPlayerActivity:

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
        initViews();
        ......

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
2
  • you mean orientation changes? Commented Dec 9, 2013 at 15:02
  • No. My VideoPlayerActivity can rotate according to device orientation. If I start VideoPlayerActivity in portrait mode. It's ok. But If I start it in landscape mode from MainMenuActivity and press Back button immediately. It causes MainMenuActivity destroyed and recreated (my log cat) and get Exception. Commented Dec 9, 2013 at 15:28

2 Answers 2

1

Rotating the device, means the system has to load new resources. E.g. you might have different resources in some layout-land folder, which needs to be loaded. To be able to load these new resources, the activity is destroyed and re-created with the new drawables/layouts/values etc etc. Android has a special mechanism for such changes, called configChanges. This includes device rotation, but also changing the phones language, etc etc.

To avoid your activity from being destroyed you can declare in your AndroidManifest.xml, that you will handle orientation changes yourself by setting this flag:

<activity
    android:name=".VideoPlayerActivity"
    android:configChanges="orientation|screenSize" />

and in your activity, add this code:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

For more info, see this link to the developer documentation

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your time. But I want my VideoPlayerActivity to be rotated according to device orientation. IF I start VideoPlayerActivity, then press Back button later. It's ok. But if I press Back button immediately(nearly the same at statring VideoPlayerActivity), It caused exception. This causes my MainMenuActivity (the one starts VideoPlayerActivity). I really don't know why
0

I don't know why It cause MainMenuActivity destroyed and recreated 2 times because of MainMenuActivity is rotated.(I don't see MainMenuActivity is rotated, just guess from the logcat). To avoid this, I add android:configChanges="orientation|keyboardHidden|screenSize" in manifiest.xml

<activity
      android:name=".activity.MainMenuActivity"
      android:screenOrientation="portrait"
      android:configChanges="orientation|keyboardHidden|screenSize"/>

Now I can see the log in onConfigurationChanged() in MainMenuActivity and avoid MainMenuActivity is destroyed and recreated. But I still don't know why it is destroyed. Here is the log cat now:

12-10 00:00:16.865: E/VideoPlayerActivity(20105): onPause()
12-10 00:00:16.885: E/MainMenuActivity(20105): onConfigurationChanged LANDSCAPE
12-10 00:00:16.885: E/MainMenuActivity(20105): onResume()
12-10 00:00:17.296: E/MainMenuActivity(20105): onConfigurationChanged PORTRAIT
12-10 00:00:17.686: E/VideoPlayerActivity(20105): onStop()
12-10 00:00:17.686: E/VideoPlayerActivity(20105): onDestroy()

5 Comments

You'd better fix this the proper way and then disable orientation if you need to. Because there are cases when Activity is recreated by the system and you will probably get the same crash.
Do you know why MainMenuActivity is destroyed and recreated? (even 2 times). If I press Back button easily. It works fine. Otherwise I press Back button immediately, It crashed. The MainMenuActivity is recreated.
It is recreated after rotation if you don't handle configChanges yourself. You get the crash because you've done something wrong. You did not provide enough code to see what exactly is wrong.
But in manifiest.xml, I set android:screenOrientation="portrait" to MainMenuActivity. Why it is recreated? If I press Back button after starting VideoPlayerActivity about 1 second. It works fine. MainMenuActivity isn't recreated. Otherwise, I press Back button immediately after starting VideoPlayerActivity. It is recreated.
The case you are describing sounds like it is being destroyed because the lack of resources when you play the video. Anyway it's normal for Android. When you press back it is re-created. To avoid crashes you need to follow these rules: don't reference Activity or it's Views fro outside the Activity. Try to reference Activity in Fragment only for short periods and only when necessary, mostly in onCreate or onCreateView. If AsyncTasks are started, cancel them in Activity onStop. Always check for null after getting in Fragment's getActivity().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.