My application have two activities, say MainActivity and SecondActivity. Main activity is declared as android:launchMode="singleInstance" and its orientation is always portrait. Second activity is always has landscape orientation.
In some devices, everything is alright and in task manager there is only one instance of my app, but in some devices (like Samsung S7), when I launch SecondActivity, there will be two instances of my app in task manager like this image:
My guess is that something is wrong with the launchMode of the MainActivty but I need it to be singleInstance. Any suggestion?
EDIT:
MainActivity in manifest:
<activity
android:name=".Activities.MainActivity"
android:screenOrientation="portrait"
android:launchMode="singleInstance"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and second:
<activity
android:name=".Activities.SecondActivity"
android:screenOrientation="landscape" />
launching code:
Intent intent = new Intent(getActivity(),
intent.putExtra("VideoUri", filmGet.getOutput().getData().getFilmTrailer());
startActivity(intent);
If it helps, I launch SecondActivity from a fragment.
So, after reading #sharan comment and some googling, it made me to read some google documents. According to docs, there isn't any difference between android:launchMode=singleInstance and android:launchMode=singleTask but one. They both make your activity singleton and so you will never have two instances of it. The only difference between them is that singleInstance will prevent the task from attaching any other activity while singleTask has not this limitation. Any other things about them are the same.
So, for anyone who is reading this post, I'll recommend you to never use singleInstance launch mode unless you exactly need what it has. Because if you have only one activity in your app, then there will be no differences between singleInstance and singleTask. And if you have more than one activity, then I'll recommend you to all of your activities belong to one task.
In short, change singleInstance to singleTask and you are go.
Related
The launcher activity of my app is defined with this intent-filter
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
I specified the launchMode for this activity as singleTask.
According to the second answer of this question - Android default launchMode of LAUNCHER activity? it shouldn't make any difference. But in my case every time I minimise the app and then relaunch it using the app icon the LauncherActivity is being brought to the forefront with intent flags - FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_RESET_TASK_IF_NEEDED and FLAG_ACTIVITY_BROUGHT_TO_FRONT. This is causing the LauncherActivity to start on top of the existing task.
While for standard and singleTop launch modes there is no problem. The LaunchActivity is not being instantiated again.
Is this an anomaly or am I somewhere wrong in my understanding?
I'm developing custom launcher app containing a WebView. When I launch app as a normal app, it works without any issues, after calling startActivity()/ startActivityForResult() (Intent.ACTION_CALL, doesn't occur when using Intent for MediaStore.ACTION_IMAGE_CAPTURE) application calls onPause(), onStop() and other activity starts, after completing its task goes back to the application. However when I set application as launcher, it calls onDestroy() right after onPause() and onStop(). Such behaviour is not desired because I'm trying to keep inserted data in the launcher WebView app.
There are also many errors in logcat right after onDestroy() similar or same as E/libGLESv2﹕ HWUI Protection: wrong calling from app context F:ES3-glDeleteBuffers (when not using it as launcher such errors appear, but sporadically and in different situations).
AppManifest contains
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
I also tried using singleInstance, with that mode application works correctly after installation, but breaks its behaviour after restart.
Using minSdkVersion 19, tested on Android 4.4.2.
Ok, so here's how I managed to solve the issue, and actually what was the problem. I used
Settings.System.putInt(
getContentResolver(),
Settings.System.USER_ROTATION,
// toRotate //Or a different ROTATION_ constant
Surface.ROTATION_270
);
for screen rotation, because I needed to be sure the app was running in landscape mode. The thing is, camera supports landscape mode, but dialer doesn't. So when I launched camera it was without issues, but dialer caused portrait rotation and that caused WebView's default behaviour when rotating the screen, onDestroy() and that causes reload afterwards...
Let begin by changing it to something like this,
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Now lets understand what launchMode(s) are
via the documentation:
android:launchMode
An instruction on how the activity should be launched. There are four modes that work in conjunction with activity flags
(FLAG_ACTIVITY_ constants) in Intent objects to determine what should
happen when the activity is called upon to handle an intent. They are:
"standard" "singleTop" "singleTask" "singleInstance" The default
mode is "standard".*
"singleTask" Does not allow Multiple Instances The system creates the activity at the root of a new task and routes the intent
to it. However, if an instance of the activity already exists, the
system routes the intent to existing instance through a call to its
onNewIntent() method, rather than creating a new one.
"standard" Default. The system always creates a new instance of
the activity in the target task and routes the intent to it.
"singleTop" If an instance of the activity already exists at
the top of the target task, the system routes the intent to that
instance through a call to its onNewIntent() method, rather than
creating a new instance of the activity.
singleInstance" Same as "singleTask", except that the system doesn't launch any other activities into the task holding the
instance. The activity is always the single and only member of its
task.
For more in depth refer to the Documentation
In my application I have three activities:
<activity
android:name="com.example.myapp.SplashScreenActivity"
android:exported="true"
android:launchMode="singleInstance"
android:noHistory="true"
android:screenOrientation="sensorLandscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.myapp.MainActivity"
android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="sensorLandscape" >
</activity>
<activity
android:name="com.example.myapp.ListActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="sensorLandscape" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myapp.MainActivity" />
</activity>
The first one is the LAUNCHER, SplashScreenActivity, which is a splash screen that disappears quite soon and it's not shown in recent activities, it starts MainActivity. In MainActivity users can select a category and ListActivity shows the items belonging to the given category. This is done with the following code:
Intent i = new Intent(getActivity(),ListActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
i.putExtra("category",mCategory);
startActivity(i);
In ListActivity the onResume method checks for the "category" extra and shows data accordingly. Since Activity launchMode is singleTop, I've also overridden the onNewIntent method to set the new Intent of the Activity.
This works properly if the app doesn't go in background: in this case, when I restart MainActivity and select a category, ListActivity resumes the old Activity showing data belonging to the previously chosen category.
How should I fix flags/launchMode in such way that my app doesn't resume ListActivity with the old data loaded?
You should not use the special launch modes. These are rarely required and only in very specific circumstances. Remove all the launchMode specifiers from your manifest. You also don't need to use these flags when launching ListActivity from MainActivity:
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Your use of singleInstance launch mode is causing you all these problems.
Assuming you would ditch all the launchModes and Flags, then activity lifecycle gives you all the information needed to implement application as you have described - maybe there is somethings you have not added?
Once application goes to background, then ListActivity will be allowed to save its state, even if system will kill your process (lack of memory etc.), then still - launching back your app will first bring back ListActivity with previously saved instance state. So you will not have behaviour as you describe : when I restart MainActivity and select a category, ListActivity resumes the old Activity showing data belonging to the previously chosen category.
Still, if you need to keep to your current design, then you should somehow inform ListActivity of new data changes, question is if ListActivity.onNewIntent is being called at all in the case your describe? Have you tried adding Intent.FLAG_ACTIVITY_SINGLE_TOP : as per this blog entry: http://www.acnenomor.com/1094151p2/bug-onnewintent-not-called-for-singletop-activity-with-intentflagactivitynewtask ?
Hi I have a Broadcast receiver with following code.
1. Intent i = new Intent(context, A.class);
2. i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3. context.startActivity(i);
This works fine and my activity does start, but it starts on top of my main activity i.e. B. What I want is that from my broadcast receiver I should be able start an Activity A, such that it does not start on top of B. Why B is always starting in background. What I am doing wrong.
Also, to mention by activity A has Theme.Dialog.
Please let me know your thoughts.
A new activity is supposed to start on top of existing activities.
If you want to start something without appearing in the activity history stack, maybe this something shouldn't be an Activity but a Service instead?
Edit: I think you can change this behaviour with FLAG_ACTIVITY_NEW_TASK in conjunction with android:launchMode="singleTask" in the Manifest. (see documentation on launch mode)
If you start an Activity then of course it will come foreground.The activity previously was in foreground will go to the background automatically.
If you don't need to start it on top of B,what about to start it from service?.Let Activity A stay as it is.
If you need to access anything from service and no need to show the activity,then surely you are looking for other then starting an Activity with an intent.
Finally if you really want to start Activity A,and B will be on top then start Activity B after starting A
I think you mean you want to start the application with a different activity. You can edit your AndroidManifest.xml file to make a different activity start first.
EDIT: Heres an example:
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainActivity" <-this will start first
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name =".otherActivity"
android:theme="#android:style/Theme.Dialog">
</activity>
<activity android:name=".anotherActivity"></activity>
</application>
I have a ListActivity and a MapActivity. I would like to launch either one of these activities on application startup that has been chosen by the user in a preferences window.
So far the only way I see to launch an activity on application startup is to specify it in the application manifest file using...
<activity android:name=".MyActiivty"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I am thinking I might have to start an activity that does nothing but looks at the user preferences and then launches either the ListActivity or MapActivity. Seems like a waste to have an activity do nothing but launch another activity. In my research I have not found any solution to this problem. Any suggestions would be greatly appreciated.
Thanks & Regards,
Dave
First, don't create some third activity. Just have the LAUNCHER Activity be either the list or the map, and have it call startActivity() on the other one (plus finish()) in onCreate() before calling setContentView() when needed. That way, ~50% of the time, you're launching the right activity.
In principle, you could have both activities have a LAUNCHER <intent-filter>, only enabling one. However, that will not work with desktop shortcuts, which will route to a specific activity (whichever one happened to be configured when they made the shortcut). If this does not concern you, you might go this route. However, try to test it with a few devices and custom home screens -- I'm not sure if everyone will pick up on your change immediately.
I just added the following code to the onCreate() method an it worked like a charm.
Intent intent;
intent = new Intent(this, MyMap.class);
startActivity( intent );
finish();
for new folks (me), following is dave's answer, plus changes i needed to make to AndroidManifest.xml.
Main activity:
Intent intent;
intent = new Intent(this, DisplayMessageActivity.class);
startActivity( intent );
changes to xml file, from -> http://developer.android.com/training/basics/firstapp/starting-activity.html
AndroidManifest.xml:
<activity
android:name="com.mycompany.myfirstapp.DisplayMessageActivity"
android:label="#string/title_activity_display_message"
android:parentActivityName="com.mycompany.myfirstapp.MyActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.mycompany.myfirstapp.MyActivity" />
</activity>