I have an application that has one service and 2 activities.One activity (the main one) is a preferences activity and the other one is a dialog themed activity. The service from time to time needs to open only the dialog themed activity (using FLAG_ACTIVITY_NEW_TASK).
The problem is that when the preferences activity is opened in background (for example the user pressed HOME key instead of BACK, so the activity is OnPause) and the service tries to open the dialog themed activity, also the main activity is opened (comes in foreground).
I don't want this. So, how can I open only the themed activity from the service, without the main activity pop up ?
Android Manifest .xml
<service android:name=".SimpleService"> </service>
<activity
android:name=".Preferences" 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=".popup_activity" android:theme="#android:style/Theme.Dialog" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="screenon.popup.activity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And from the service :
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory("screenon.popup.activity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
I believe you're looking for the android:launchMode attribute.
Alex , I believe that all you want is to display preferences activity just once & then it must die(or lets say finish()) .
In that case you can override onResume of the preferences activity
to finish your preferences activity after it is resumed after pause
#Override
public void onResume()
{
//if activity is resumed after onPause then only run it
this.finish(); //simply kill your activity if it is resumed after pause
}
EDIT-To know whether the activity was paused you need to override onPause().I think you can dig out the rest.
Hope it helps!
Related
I am developing an android app which has 2 methodes of starting.
One is the normal way by pressing the app icon on the phone.
The other method is with a deep link from a website.
The deeplink also sends some data which the app needs to do some "stuff". However this should only be done once.
When the deeplink activity is finished it start the main activity. However when I press back (on the device) and open the app from recents it opens the deeplink activity again.
I could exclude the deeplink activity from the recents in the manifest. This also excludes the mainactivity from the recent apps, this should not be the case.
How do I prevent the deeplink activity from beeing started from the recent apps?
My Manifest:
<activity
android:name="MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="#style/AppTheme">
</activity>
<activity
android:name="DeeplinkActivity"
android:label="#string/app_name"
android:noHistory="true"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app_name" android:host="test" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="test" android:path="/" android:scheme="app_name" />
</intent-filter>
</activity>
To switch to the MainActivity I do the following:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
EDIT:
This post was marked as duplicate with: Android: Starting app from 'recent applications' starts it with the last set of extras used in an intent
However that post is regarding the same activity. I want to change the root activity so when I start the app from recents it does not start the DeeplinkActivity. Yes as a workaround I could check the Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY flag. But then every time the user starts the app from recents the DeeplinkActivity is opened whilst it is not needed anymore.
Setting and or clearing aditional intent values does not seem to work.
I use information from the getIntent().getData()
If you still feel as if this is a duplicate please explain.
Your problem is that both DeepLinkActivity and MainActivity are in the same task, so when the user selects the app from the list of recent tasks, Android will either bring an existing task to the foreground, or if there is no existing task (with live/active activities in it), start the Activity that was the root Activity in the most recent task. You can't predict which Activity will be the root Activity, since the task could be started with either DeepLinkActivity or MainActivity, depending on which one the user chose first.
You really need to have 2 separate tasks to do this. One task will have your DeepLinkActivity in it, and this task should be excluded from the "recent task list". The other task will have your MainActivity in it.
I assume that MainActivity has the <intent-filter> with ACTION=MAIN and CATEGORY=LAUNCHER, even though your posted manifest does not show this.
Your manifest should look like this:
<activity
android:name="MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="DeeplinkActivity"
android:label="#string/app_name"
android:noHistory="true"
android:screenOrientation="portrait"
android:taskAffinity=""
android:excludeFromRecents="true"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app_name" android:host="test" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="test" android:path="/" android:scheme="app_name" />
</intent-filter>
</activity>
You definitely do not need launchMode="singleTask" for MainActivity and you probably don't need it for DeepLinkActivity either (that depends on what else you do with this).
Specifying taskAffinity="" ensures that DeepLinkActivity is not launched into the same task as MainActivity, and allows you to launch MainActivity from DeepLinkActivity in a separate task. NOTE: Without specifying taskAffinity, both activities will end up in the same task, even though you specify launchMode="singleTask" for both of them.
Specifying excludeFromRecents="true" on DeepLinkActivity tells Android that the task with DeepLinkActivity as its root activity should not appear in the list of recent tasks.
When you launch MainActivity from DeepLinkActivity, you should do this:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
and make sure that you call finish() on DeepLinkActivity.
If necessary you can also add noHistory="true" to DeepLinkActivity, but I don't think it is necessary. If the user is in DeepLinkActivity and gets an incoming phone call, after the phone call is ended, DeepLinkActivity should be displayed. If you specify noHistory="true", DeepLinkActivity would be finished immediately when the user accepts the incoming phone call.
Let me know if this is clear and works for you.
I have an activity 'A' defined in Manifest like below:
<activity
android:name=".A"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
When I launch my APP, that activity is always loaded from the start. It wont start from my prev activity.
When I remove android:launchMode, then it works as I expect.
Since you set android:launchMode="singleTask", the activity A will always be the root of your activities.
From DOCS:
In contrast, "singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
Default mode is standard. So, when you remove android:launchMode="singleTask", your APP returns to standard launch mode.
That's why if you app is always starting Activity A.
If you would like to start a different Activity on launch replace that in the xml name attribute that contains LAUNCHER
<activity
android:name=".ActivityB"
android:launchMode="singleTask"
android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Where Activity B is an alternate activity.
My current MainActivity is a navigation drawer.
I want to make another activity on top of the navigation drawer.
Lets make that activity StartActivity.
On StartActivity there is a start button.
What i want to do is make the StartActivity opens up first when the app runs.
And when the user presses the START button on the StartActivity, it will direct him/her to the navigation drawer.
is this possible?
Create the StartActivity.
somewhere call "startActivity(intentforMainactivity);
go to the manifest and move
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
from the
<activity
android:name="sehtestapp.MainActivity"
into
<activity
android:name="sehtestapp.StartActivity"
Your Application will then start the StartActivity first
1) Create another Activity, that you'll call StartActivity
2) Set up a layout that you'll use in your StartActivity with a
button in it.
3)Create the onClickListener to launch a new Intent when clicked.
Make it launch the MainActivity.
4) Change your AndroidManifest as follow :
<activity
android:name="XXX.StartActivity"
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="XXX.MainActivity"
android:parentActivityName="XXX.StartActivity" />
You can try changing the Launcher activity and send intent having a boolean bundled in it when START button is pressed, in MainActivity fetch the intent, read that boolean value and open the drawer programmatically.
I have activity A that is the MAIN and activity B that is another activity that i use for the app. Now, i want to execute the app B only if is called by NFC tag.
I wrote an NFC tag that runs the app com.test.nfc)" (that is the package of my test app). It works, but it runs the MAIN (activity A) of course, and is not what i want.
If i use NFC i want that the main app will be the Activity B (i repeat, only if i run the app with NFC). Is there any way?
I tried to launch the activity using the Tasker app from PlayStore, but it works only if this app is installed, if i uninstall it, it not work anymore.
Just set the intent-filter for the activity you want to run only on NFC then on your manifest.xml
<activity
android:name="com.activity.a"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.activity.b"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="ext"
android:pathPrefix="/com.example:ddcnfc"
android:scheme="vnd.android.nfc" />
</intent-filter>
</activity>
In the above example, activty A runs from Launcher, activty B from NFC.
Then in the onResume function of activty B class,
#Override
public void onResume() {
super.onResume();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
//Your initialization goes here
}
}
I have 3 activities, then I navigate from A to B and from B to C. The stack are C-B-A (with C on the top). The C Activity have a Runnable that works every interval, and connect to a web service that update the UI. If the Activity C comes to background, is destroyed and then comes to foreground again the task starts with de main Activity A. I want to come back to the C activity. Is possible?
In the emulator works fine but in my smartphone with only this application running, always destory the entire application.. can I do somthing? If I do a service separated from the UI, could improve this?
Edit2: I try this declaration on AndroidManifest
<activity android:name=".ActivityA" android:label="#string/app_name"
android:alwaysRetainTaskState="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="oauthht" android:host="hattrick"/>
</intent-filter>
</activity>
<activity android:name=".ActivityB" android:label="#string/ActivityB"
android:screenOrientation="portrait"></activity>
<activity android:name=".ActivityC" android:label="#string/ActivityC"
android:screenOrientation="portrait"
android:launchMode="singleTask">
Edit2: And the code to call the activities:
In the main Activity A:
public void onClickButtonB(View button) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(this,ActivityB.class));
startActivity(intent);
}
In the Activity B:
Bundle bundle = new Bundle();
bundle.putLong("selectedMatch", matchID);
Intent liveIntent = new Intent();
liveIntent.setComponent(new ComponentName(ActivityB.this, ActivityC.class));
liveIntent.putExtras(bundle);
startActivity(liveIntent);
I know which was the problem. The application crashes in background but the exception was caught. This restarts the app in background and mislead me. :-S