Reputation: 8271
This question is a spin-off from a suggestion made in How to close or stop an external app that I started in Android.
I'm writing an Android app which is a remote-control for an industrial process - the process runs on a PC which is in constant communication with my Android app, Occasionally the PC sends a PDF file to the Android and I launch the AdobeReader.apk to display it. When the PC dismisses the image I want to dismiss it on the Android.
In the link above I was told that once I launch the AdobeReader there's no way to shut it down from my code. However I might be able to bring my app back to the front, which is just as good for my purposes. But I haven't been able to get it to work. The main activity for my app is RemoteControlActivity and I tried:
try {
Intent i = new Intent(ctx, RemoteControlActivity.class);
ctx.startActivity(i);
}
catch (ActivityNotFoundException e) {
Log.d("ShowButtons(normal)", "Hide");
}
I also tried adding an intent.setFlags(...) before the startActivity() call with various combinations of Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_FROM_BACKGROUND with no luck.
In the manifest the launch mode for remoteControlActivity is singleTask
In the debugger the StartActivity() is called without landing in the Catch clause but I don't hit a breakpoint in RemoteControlActivity's onRestart or onResume handlers.
Thanks in advance!
EDIT: An answer, below, suggested a different flag so I tried it:
try {
Intent i = new Intent(ctx, RemoteControlActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
ctx.startActivity(i);
}
catch (ActivityNotFoundException e) {
Log.d("ShowButtons(normal)", "Hide");
}
... but no luck - in the debugger it calls startActivity, does not land in the catch block, but nothing happens.
Further Edit: I was asked for the Manifest; here's the part for the main Activity:
<activity android:launchMode="singleTask"
android:label="@string/app_name"
android:windowNoTitle="false"
android:configChanges="orientation"
android:screenOrientation="landscape"
android:name="RemoteControlActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Upvotes: 6
Views: 14540
Reputation: 1018
Please use -
FLAG_ACTIVITY_REORDER_TO_FRONT
For example if present task is like - A, B, C, D. And if, D calls startActivity() for B with FLAG_ACTIVITY_REORDER_TO_FRONT
, then B will be brought to the front, new task stake will be like - A, C, D, B.
Upvotes: 1
Reputation: 5659
Your application cannot kill another 3rd party external application regardless of how that external app was launched unless it shares the same processId as your application, or you rooted your device.
You can, however, bring your application's activity back to the top (or foreground) even after launching an external 3rd party app by using the Application Context and not the activity context. This is accomplished with the following method:
private void bringMyAppToForeground(Context context) {
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(getPackageName(), SplashScreenActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(it);
}
where "intent.my.action"
is defined in the manifest as follows:
<activity
android:name="com.example.SplashScreenActivity" >
<intent-filter>
<action android:name="intent.my.action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Note that the activity that called the intent to launch the external app should not be the one to call bringMyAppToForeground(); instead, this method should be called from another activity (or a service), because otherwise that means the activity is trying to start itself and that will cause activity lifecyle complications.
Upvotes: 2
Reputation: 21
You can try this:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Upvotes: 2
Reputation: 56
The best option in this case is to kill the "adobe reader" (or whatever app) process. Using the android Intent class in this case is useless since we're not dealing with activities within the same application.
Killing a process can be done on 2 steps in a rooted android device :
1- Get the "adobe reader" pid : we assume that adobe_reader_package_name is a String containing the adobe reader package name
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> pids = am.getRunningAppProcesses();
int processid = 0;
for (int i = 0; i < pids.size(); i++) {
ActivityManager.RunningAppProcessInfo info = pids.get(i);
if (info.processName.equalsIgnoreCase(adobe_reader_package_name)) {
processid = info.pid;
}
}
2- Killing the process using its pid: this can be done using a method like this
public static void doCmds(List<String> cmds) throws Exception {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd+"\n");
}
os.writeBytes("exit\n");
os.flush();
os.close();
process.waitFor();
}
and calling it as follow :
List<String> cmdList = new ArrayList<String>();
cmdList.add("kill -9 "+processid);
try {
doCmds(cmdList);
Log.d("A3", "kill process completed ...");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Hope this helps, cheers !!
source-1 : android : how to run a shell command from within code
source-2 : How to get pid of android application with out using adb shell?
Upvotes: 0
Reputation: 1006744
If the activity is likely already running, use FLAG_ACTIVITY_REORDER_TO_FRONT
. Or, use both FLAG_ACTIVITY_CLEAR_TOP
and FLAG_ACTIVITY_SINGLE_TOP
.
Upvotes: 1
Reputation: 95578
Flag Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
is only set by Android when it brings an activity to the front itself. Setting it yourself does nothing.
Flag Intent.FLAG_FROM_BACKGROUND
doesn't do anything, it is only used for informational purposes (to indicate that the activity was started by a background task).
You need to set Intent.FLAG_ACTIVITY_NEW_TASK
. From the documentation for FLAG_ACTIVITY_NEW_TASK
:
When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in.
Upvotes: 5