My app contains fragments, and it's mainly a fragment application. I have only 3 activities, others are all fragments. But from any point of the app when I rotate the phone in landscape mode or portrait the application restarts and continues from the Start Point of the app, from the beginning.
I put the android:configChanges="orientation|keyboardHidden|keyboard"
in the Manifest, but it seems it has no effect at all. I'm populating the fragments only with one web view. But I also change the actionbar color. That's all I do in the app. It's a static app, there is no user input. Here's a sample code of how my fragments look like:
public class CLASSNAME extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRetainInstance(true);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.LAYOUT, container, false);
ActionBar bar = getActivity().getActionBar();
bar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.COLOR)));
bar.setTitle("TITLE");
final WebView wFirst = (WebView) view.findViewById(R.id.WEBVIEWID);
wFirst.getSettings().setJavaScriptEnabled(true);
wFirst.setBackgroundColor(0x00000000);
wFirst.loadDataWithBaseURL(LOADING DATA);
wFirst.setWebViewClient(new WebViewClient() {SETTING UP WEBVIEW CLIENT});
return view;
}
}
I read lots of posts that got answered with Save Instance State and those other methods, but in my case I have no idea what to save and how to keep my activity rolling even if the orientation is changed.
This is the MainActivity.class code:
public class MainActivity extends Activity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
private NavigationDrawerFragment mNavigationDrawerFragment;
private static CharSequence mTitle;
public static Context context;
public static Context getContext() {
return context;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
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
protected void onDestroy() {
super.onDestroy();
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
switch (position) {
case 1:
fragmentManager.beginTransaction()
.replace(R.id.container, new AlgebraicGraphs())
.commit();
break;
case 2:
fragmentManager.beginTransaction()
.replace(R.id.container, new Logarithms())
.commit();
break;
case 3:
fragmentManager.beginTransaction()
.replace(R.id.container, new Polynomials())
.commit();
break;
case 4:
fragmentManager.beginTransaction()
.replace(R.id.container, new Powers())
.commit();
break;
case 6:
fragmentManager.beginTransaction()
.replace(R.id.container, new AreaFormulas())
.commit();
break;
case 7:
fragmentManager.beginTransaction()
.replace(R.id.container, new SurfaceAreaFormulas())
.commit();
break;
case 8:
fragmentManager.beginTransaction()
.replace(R.id.container, new PerimeterFormulas())
.commit();
break;
case 9:
fragmentManager.beginTransaction()
.replace(R.id.container, new VolumeFormulas())
.commit();
break;
case 11:
fragmentManager.beginTransaction()
.replace(R.id.container, new TrigonometryGraphsFormulas())
.commit();
break;
case 12:
fragmentManager.beginTransaction()
.replace(R.id.container, new HyperbolicIdentities())
.commit();
break;
case 13:
fragmentManager.beginTransaction()
.replace(R.id.container, new TrigonometricIdentities())
.commit();
break;
case 16:
fragmentManager.beginTransaction()
.replace(R.id.container, new IntegralIdentities())
.commit();
break;
case 17:
fragmentManager.beginTransaction()
.replace(R.id.container, new IntegralSpecialFunctions())
.commit();
break;
case 18:
fragmentManager.beginTransaction()
.replace(R.id.container, new TableOfIntegrals())
.commit();
break;
case 20:
fragmentManager.beginTransaction()
.replace(R.id.container, new DerivativeIdentities())
.commit();
break;
case 21:
fragmentManager.beginTransaction()
.replace(R.id.container, new TableOfDerivatives())
.commit();
break;
default:
fragmentManager.beginTransaction()
.replace(R.id.container, new DefaultLayout())
.commit();
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_about) {
About about = new About();
about.show(getFragmentManager(), "about");
}
return false;
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
This is the log:
02-19 06:41:24.849 9788-9788/l.pocketformulas E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalStateException: Fragment Logarithms{4132f5d0} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:828)
at l.pocketformulas.Logarithms$1.onPageFinished(Logarithms.java:71)
at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:444)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5520)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)
at dalvik.system.NativeStart.main(Native Method)
Use this in you AndroidMenifest.xml
<activity
android:name="MyActivity"
android:configChanges="orientation|keyboard|keyboardHidden"
android:screenOrientation="sensor" />
Android restarts the activities whenever the orientation change by default.
You will need to save your data/state by calling onSaveInstanceState()
before Android destroys the activities.
Have a look here: Handling Runtime Changes
You could prevent this by adding android:configChanges="orientation"
to your activity in AndroidManifest file
.
Updates:
When a config change occurs the old Fragment isn't destroyed -- it adds itself back to the Activity when it's recreated. You can stop errors occurring by using the same Fragment rather than recreating a new one. Simply add this code:
if(savedInstanceState == null)
{
mFragmentManager = getFragmentManager(); // **update**
FragmentTransaction ft= mFragmentManager.beginTransaction();
MyFragment fragment = new MyFragment();
ft.add(R.id.container, fragment);
ft.commit();
}
Be warned though: problems will occur if you try and access Activity Views from inside the Fragment as the lifecycles will subtly change. (Getting Views from a parent Activity from a Fragment isn't easy).
In OnCreate()
method of your main activity use this code:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Or you can also set Orientation
in manifest.xml
like:
<activity
android:name="com.example.fragment.AppMainTabActivity"
android:configChanges="keyboardHidden|orientation"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustPan" >
</activity>
Now your orientation will be set to portrait and will never change.
Update:
@Override
protected void onSaveInstanceState(Bundle outState) {
webView.saveState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
}
Now, your onCreate()
implement like:
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.blah);
if (savedInstanceState != null)
((WebView)findViewById(R.id.webview)).restoreState(savedInstanceState);
}
These methods can be overridden on any activity, it just basically allows you to save and restore values each time an activity is created/destroyed, when the screen orientation changes the activity gets destroyed and recreated in the background, so therefore you could use these methods to temporary store/restore states during the change.
For an example go to this page :http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/
I did solve this problem with a simple configuration on "AndroidManifest.xml":
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
have you checked this?
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Depending on your device you may need to include "screenSize" in confingChange. other wise your activity will restarted.
like this:
<activity
android:name="MyActivity"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
android:screenOrientation="sensor" />
User contributions licensed under CC BY-SA 3.0