My app contains two activity, one widget and a broadcast receiver.
First activity is default one which is called by home launcher. Second activity is a reminder dialog activity which plays a MP3 and has a dismiss button. It will appear on home screen.
My widget is a custom clock which setup an alarm to call a broadcast receiver every minutes which is responsible to update the clock. There are some reminders at specific time which broadcast receiver calls the reminder activity.
My app now is fully working, but there is a small problem: When app is open in the background (It's not on screen), when broadcast receiver start the reminder activity, the default activity comes first and reminder activity is shown over that. But when I close the app, reminder activity appears on home screen and there is no problem.
This is the code I use to startActivity from receiver:
context.startActivity(new Intent(context, ActivityReminder.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP));
And this is android manifest:
<activity android:name=".MyActivity"
android:theme="#android:style/Theme.Black.NoTitleBar"
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=".ActivityReminder" android:label="#string/reminder" android:screenOrientation="portrait" android:theme="#style/Theme.CustomDialog" />
<receiver android:name=".widget"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget" />
</receiver>
<receiver android:name=".UpdaterReceiver" />
For now I use this workaround in the default activity to solve the problem, it work just like closing the app:
#Override
protected void onPause()
{
super.onPause();
finish();
}
I found something more annoying. If the main activity is not closed, every call from broadcast receiver opens the activity again even it's open already. Although if the main activity is closed, subsequent call won't do anything.
Your problem is taskAffinity. When you launch ActivityReminder, Android tries to find an appropriate task to launch this into. If your app is not running, it won't find an appropriate task, so it will start a new one and the Activity will show up in a task by itself. However, if your app is already running in the background, Android will bring the existing task to the foreground and launch ActivityReminder into that task.
To solve the problem, add the following to the <activity> definition for ActivityReminder:
android:taskAffinity=""
This tells Android that it shouldn't look for a "matching" task to launch ActivityReminder into.
Related
The following situation:
app is started from a deep link (sms) and launches the MainActivity
user presses the start button in the app which opens SecondActivity
app goes into background
user presses on app icon again in launcher => HERE I EXPECT the SecondActivity be still active. But instead, MainActivity is relaunched.
Tried with "singleTop" activity mode - no difference.
SecondActivity is launched from MainActivity without any special intent flags, plain startActivity()
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:alwaysRetainTaskState="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">
<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”/>
It turned out there are two reasons:
Starting app from deep link created separate instance of the app => solved by specifying "singleTask"
The SecondActivity was destroyed at some point, which explains why starting the app again from icon will bring MainActivity screen
Thanks all commenters for helpful hints!
When starting the secondActivity you can just call finish() in the firstActivity (for example in onPause() or buttonClick() firstActivity). In this way, your app is still running (i.e secondActivity). When you launch the app the secondActivity should run directly (if the app is not totally destroyed yet).
I have two applications installed on my device, application A and application B.
When a user launches application A, they press a button to launch application B.
I use the following code:
Intent intent = Global.CurrentContext.getPackageManager().getLaunchIntentForPackage("some.random.app");
Global.CurrentContext.startActivity(intent);
The first time the user does this, it works fine and works as expected, however, if the user then launches the phones task manager and swipes away application B. When the user then presses the button in application A. The activity is not created.
I believe this is something to do with the way that the task and the activity are being destroyed by android. My thought process is that when the user swipes to kill application B that the activity is destroyed, but the task remains. Then the second time they press the button in application A, that it's attaching to the old task and then not showing for the user.
Application A's activity manifest for the activity:
<activity
android:name="a.a.a.LogonActivity"
android:label="#string/app_name"
android:noHistory="true"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.Light.NoTitleBar"
android:windowSoftInputMode="stateHidden"/>
Application B's activity manifest for the activity:
<activity
android:name=".activity.HomeActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
When I set android:noHistory="false", it works. I think it is android:noHistory="true" killed applicationA's top activity, makes it doesn't work.
I am developing an hybrid app using IBM worklight where I have to open another webview on the top of existing webview(Cordova webview),so i created a new activity(WebView Activity) to load my external page,but when i am going to background from webview activity by pressing home button and again coming to foreground my MainActivity getting called and restarts the app,I have used singleTop for my MainActivity in manifest file
<activity android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboardHidden|screenLayout|screenSize"
android:launchMode="singleTop"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="com.main.sample.NOTIFICATION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name=".WebViewActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboardHidden|screenLayout|screenSize"
android:launchMode="singleTop"
android:theme="#style/Theme.Transparent">
</activity>
I don't know why it is happening,I want my last activity to get resumed instead of main activity
Read documentation for the modes.This will explain you about what is happening:
"singleTask" and "singleInstance", should be used only when the > activity has an ACTION_MAIN and a CATEGORY_LAUNCHER filter. > Imagine, for example, what could happen if the filter is missing: An > intent launches a "singleTask" activity, initiating a new task, and > the user spends some time working in that task. The user then presses > the Home button. The task is now sent to the background and is not > visible. Now the user has no way to return to the task, because it is > not represented in the application launcher.
This is one potential solution.There are multiple ways to do this.
Try using the following code in the onCreate method of the activity that is specified as the Launcher Activity in the Manifest:
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
finish();
return;
}
This will finish your Launcher Activity before it is displayed by detecting that there is already a task running, and your app should instead resume to the last visible Activity.
I have 2 apps, one of them is calling an activity from the second one through an intent filter like so:
Call in App1 (Parent app)
Intent openApp = new Intent("com.app.intent.Activity2");
startActivity(openApp );
Intent filter in App2 (child app)
<activity
android:name=".app.activity.Activity2"
android:label="#string/app_name"
android:launchMode="singleInstance"
>
<intent-filter>
<action android:name="com.app.intent.Activity2" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
At one point the Parent application has to close but the problem is the Activity2 from the second application gets killed as well. I can see that Activity2 is actually running under the same package, is there any way to have the Activity2 persist and run even after the parent applicaiton is closed ?
Thank you
This discussion seems to have what you need. Seems like you need to get the launch intent from the package you want to launch and use that in your intent.
Launch an application from another application on Android
Android will generally run all components from the same APK in a single process, so if one of those crashes the process then they will all be gone.
You can however tell it to put an activity or service in its own process.
<activity
android:name=".app.activity.Activity2"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:process=":my_unique_process">
Of course if your process is dieing unexpectedly, that's a problem that needs to be understood and fixed - this would just be a temporary workaround.
I'm still fresh to Android and Id think the below config works for launching my service when the app launches.
<service android:name=".PlaylistUpdaterService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
But this is not the case. What did I miss?
Wrong! extend the Application class (IE make your own), then in the onCreate() method do this.
//Service is below
Intent serviceIntent = new Intent(getApplicationContext(), PlaylistUpdaterService.class);
startService(serviceIntent);
And take that intent filter crap out of your declaration in the manifest file. Leave it as
<service android:name=".PlaylistUpdaterService">
The intent filter following needs to be in your home activity only
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
The reason you do this is because the Application class is started up as soon as the app is, and acts as kind of a global class the the android framework manages.
Actually if you want the service to run every time you go back to your home screen, you should start the service in your home classes onResume(). Putting it in the applications onCreate() will only start the service if the user is launching for the first time, or after the running process has been killed. Or you could put it in your home classes onCreate() but that is not even guaranteed to run every time.
Correct me if I am wrong, but android.intent.category.LAUNCHER is valid only for Activity. So, does not look like valid way to start Service. The same you can achieve if you do the following:
create transparent Activity that will be used only to start Service
for that Activity, you do not need to specify GUI layout. So, you do not need to setContentView() in the activity's onCreate(). The only thing you need is to put
#android:style/Theme.NoDisplay
under Theme tag for this Activity in AndroidManifest.xml.
start Service from onCreate() of your Activity.
call finish() in onStart() of your Activity to close it.
So, your Activity will be invisible to the user, last shortly and nobody will notice that it was used to start the service.