6

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>
Community
  • 1
  • 1
user316117
  • 7,971
  • 20
  • 83
  • 158

6 Answers6

5

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.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • The entire manifest is huge and anyway posting it would probably violate my NDA, but I'll post the part for the main Activity and you can ask questions about the rest. – user316117 Jul 12 '12 at 15:25
  • 1
    Looks ok. Running out of ideas :-(. Have you launched the app (initially) from an IDE (Eclipse, IntelliJ, etc.)? If so, please close the app, kill it and then launch it again by clicking the app icon from the list of available apps. There is an Android bug related to launching apps from an IDE that may be showing its ugly face here. – David Wasser Jul 12 '12 at 15:32
  • I get the same behavior when I launch it from the device. Are there any diagnostics available to see what happens after the startActivity() call? – user316117 Jul 12 '12 at 16:54
  • You can look at the logcat. If you have all filtering off you can usually see messages from Android about what it does with Intents, starting activities, etc. – David Wasser Jul 12 '12 at 17:12
  • in LogCat, when I fire off the startActivity() the Activity manager shows **"07-12 14:56:13.542: I/ActivityManager(313): Starting: Intent { flg=0x20000 cmp=xxx.xxxxxx.remote/.RemoteControlActivity } from pid 5344"** . . . and that's it - nothing else about Intents, Activities, etc. – user316117 Jul 12 '12 at 19:02
  • If you do `adb shell dumpsys activity` this displays all the activities in the system including the running tasks. It might be interesting to have a look at that. Maybe we don't really understand what tasks/activities are running. Can you post that? – David Wasser Jul 13 '12 at 07:34
2

You can try this:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
2

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.

Phileo99
  • 5,581
  • 2
  • 46
  • 54
1

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.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I tried all these flags, alone and in various combinations, with no luck. I also tried changing the "catch" exception to just a generic exception instead of an ActivityNotFoundException to see if that would illuminate anything. No luck - it never takes the "catch" path but nothing ever seems to happen. So I don't think it's a flag issue; I think we need to find out what it's actually doing with the startActivity after its called. Are there any log files or diagnostics Android has that would help here? – user316117 Jul 12 '12 at 18:11
  • @user316117: Given the message you posted as a comment in the other answer, it sure seems like the activity should be taking over the foreground. Android has already resolved the activity and is starting it -- if the start failed, you would see some sort of error messages in the log. I have no explanation for the behavior you are seeing. If you get a chance to create a standalone project that can reproduce the behavior, I'd be interested in taking a peek at it. – CommonsWare Jul 12 '12 at 20:41
1

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.

CR Sardar
  • 921
  • 2
  • 17
  • 32
0

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?

Community
  • 1
  • 1
Bens.Raouf
  • 56
  • 3