3

I am trying to limit a family of applications, using the same activity (in a Library Project shared by all), so that only one such application can run at a time.

In my first round of trying to learn how to go about that, I learned that:

  1. android:launchMode="singleTask" won't do the trick.
  2. setVisible(true/false) in onResume()/onPause() respectively is the best way to tell whether my application is running. But what do I do with it once the 2nd instance knows that the 1st instance is running???

So, I am thinking of tricking the system by always returning the same instance by overriding Activity.getApplication() and returning a shared static:

public class MyApplication extends Application 
{   
    private static MyApplication s_instance;

    public MyApplication()
    {
        s_instance = this;
    }

    public static MyApplication getApplication()
    {
        return s_instance;
    }
}

(credit for the idea goes to @inazaruk)

But, like the aforementioned visibility solution, what do I do with this now?

Does the system itself use getApplication() to determine whether to launch a new instance or just bring it to the front of the stack? Is this safe?

If the answer is "no", can I just call Activity.finish() to not let the 2nd activity not even start? If so, where do I do this?

  1. Right in Activity.onCreate()?
  2. Activity.onResume()?
  3. MyApplication()? (constructor)
  4. A better place?
Community
  • 1
  • 1
ateiob
  • 9,016
  • 10
  • 44
  • 55
  • 1
    I'm a bit confused. You say _a family of applications_ but how are these packaged? On Android, an APK contains a single application. The application has a unique package name and a unique userID and runs in its own process. This means that if you have 2 applications in 2 separate packages they will run in 2 separate processes and therefore returning static instances from `getApplication()` wont do you any good at all. Please elaborate and explain more about how these applications are related to each other. – David Wasser Aug 01 '12 at 16:47
  • @DavidWasser You are absolutely correct. They run in 2 separate processes and therefore returning static instances from getApplication() don't do me any good at all. You are also right about the application package names being different, but that isn't relevant here because the shared Library Project's package name is identical. Any idea how to to track that, across different processes, in **real-time** (i.e. not through the slow shared preferences, but in faster RAM)? If you post your comment as an answer I will accept it. – ateiob Aug 01 '12 at 20:55

1 Answers1

1

I'm a bit confused. You say a family of applications but how are these packaged? On Android, an APK contains a single application. The application has a unique package name and a unique userID and runs in its own process. This means that if you have 2 applications in 2 separate packages they will run in 2 separate processes and therefore returning static instances from getApplication() won't do you any good at all.

Here's an idea that might work for you:

Every application that uses this shared-library could broadcast a sticky Intent that contains the package name of the application that is running as an Extra.

Every application that uses the shared-library could register a listener for this sticky Intent and if it gets one it can look and see if that application (the one in the Extra) is currently running. If that application is running it could just refuse to run (or warn the user and ask him if it should run, or whatever).

It is just a thought, and I've not actually tried it, but I think this could be made to do what you want.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Wonderful idea. Thanks! It would be interesting to benchmark how much faster it is than a shared preference implementation. – ateiob Aug 02 '12 at 00:42
  • After learning about this a little more, even a sticky broadcast isn't that great: http://stackoverflow.com/a/5457559/869501 . Back to square one. Perhaps the [getRunningAppProcesses()](http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses%28%29) is the preferred compromise, although "*this method is only intended for debugging or building a user-facing process management UI.*" Since these are all my own apps, let's pretend I am building "a user-facing process management UI". ;) – ateiob Aug 07 '12 at 22:01