Launching an Android Activity of another APK

We have discussed Android and its Activity system today. It is quite hard to grasp for an iOS guy like me; it feels…special.

I certainly know how to start an activity within my own app and I understand the difference of an explicit Intent vs an implicit one. But there are a couple of questions I couldn’t find answers to, particularly not something that would show how things work with Xamarin.Android.

So I created a small test app to answer the following questions:

  1. How can another app be launched directly?
  2. How can an Activity of another APK be started via an explicit Intent?
  3. How to implicitly start an Activity of another APK?

How can another app be launched directly?

Starting another app is fairly easy if you know the package identifier. All it takes is to query the main launcher Activity.

var intent = PackageManager.GetLaunchIntentForPackage("net.csharx.targetapp");
this.StartActivity(intent);

In the code snippet above “net.csharx.targetapp” is the package identifier of the app we want to launch. We can find this in the options of the Android project in the section “Android Application -> Package Name”. Launching an app this way simply works (TM) without any additional changes of the Activity to be launched.

How can an Activity of another APK be started via an explicit Intent?

The question should be first: is this possible at all? Yes, it is. However there are some preconditions.
Googling around on Bing showed that using the component name is key. But how exactly? Well, here’s an example.

var intent = new Intent();
intent.SetComponent(new ComponentName("net.csharx.targetapp", "net.csharx.targetapp.ExplicitActivityInTargetApp"));
this.StartActivity(intent);

The component name is important. The first parameter is again the package name “net.csharx.targetapp”. The second parameter has to be the fully qualified name of the target activity. In my case, that’s “net.csharx.targetapp.ExplicitActivityInTargetApp”. However this does not work out of the box. The target Activity must be setup correctly:

[Activity(Label = "Explicit in Target", Exported = true, Name="net.csharx.targetapp.ExplicitActivityInTargetApp")]
public class ExplicitActivityInTargetApp : Activity
{
...
}
  • The Activity must set its Exported flag to true. By default, an Activity cannot be launched from an external app (in other words: the value of this flag is false).
  • The Name attribute must be set to a fully qualified name. The value defined here is then used by the source app as 2nd part of the component name

The information above answers one very important question for me: yes, my Activity is safe – nobody can start it unless I export it correctly.

How to implicitly start an Activity of another APK?

Using an implicit Intent is far more common:

[Activity (Label = "Implicit in Target")]
[IntentFilter (new string[] { "net.csharx.targetapp.SOME_ACTION" }, Categories = new string[] { Intent.CategoryDefault })]
public class IntentFilterActivityInTargetApp : Activity
{
...
}

We decorate the Activity with an IntentFilter and specify an action. The action string is then used to create the implicit Intent. Something that’s not so obvious is the Categories parameter: even though it is optional, it still has to be set; otherwise, Android cannot resolve the Intent. I used the default category here. Notice that is not necessary to export this Activity! As soon as an IntentFilter is specified, it will be automatically exported!

Launching the Activity is trivial:

var intent = new Intent();
intent.SetAction("net.csharx.targetapp.SOME_ACTION");
this.StartActivity(intent);

By using a unique action string, Android will launch the Activity directly without presenting a selection dialog to users.

If you want to try out the above, grab the project from my Github account. First deploy the “TargetApp” and then the “SourceApp”.

Advertisements

One thought on “Launching an Android Activity of another APK

  1. Pingback: Adam J Wolf: Weekly Xamarin Newsletter Issue #61 | XamGeek.com

Comments are closed.