10

I have multiple ActivityAliases which all start one single TargetActivity. Inside of my TargetActivity I try to distinguish the alias that started the TargetActivity.

The aliases are defined in Manifest as launchables (intent-filter), which will be displayed as shortcuts on the homescreen. The user will click on the shortcut and android will start the activity, which I defined in the "android:targetActivity=.." tag.

For that I currently extract the componentName from the Intent, which is given to my TargetActivity and using the className().

Like:

String aliasName = targetActivity.getComponentName().getClassName();

This works fine for a lot of devices. But currently I see some failures on the OnePlus. At that device, my technique only returns the className of my TargetActivity and therefore I can't deliver the action, based on the alias that the user started.

Are there any other, reliable methods to get ActivityAlias that was used to start the TargetActivity? It does not need to be the name itself, as long as I can distinguish them. I do not want to create dedicated TargetActivities for every Alias!

Thanks!

Ps.: I saw another way, which uses the PackageManager to retrieve the activityInfo and using the Activity.name. But I doubt that this will return something different than my first approach.

ActivityInfo aInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), PackageManager.GET_META_DATA);

String aliasName = aInfo.name;

I also tried meta-data:

Edit:

Unfortunately this method does not work for all devices. If the parsed alias-className from the activity.component returns the target-activity, then the meta-data approach fails, too.

I continued searching for an answer and found a good workaround to distinguish between my aliases inside of the TargetActivty.

You can provide meta-data within your ActivityAlias tag like so:

<activity-alias 
    android:name=".aliasName" 
    android:enabled="false" 
    android:exported="true" 
    android:icon="@drawable/someIconRes" 
    android:label="@string/someLabelRes" android:targetActivity=".yourTargetActivity"> 
    <meta-data android:name="alias" android:value="valueToDistinguish"/>
    <intent-filter>  
        <action android:name="android.intent.action.MAIN"/> 
        <category android:name="android.intent.category.LAUNCHER"/> 
    </intent-filter> 
</activity-alias>

The important part here is:

<meta-data android:name="alias" android:value="valueToDistinguish"/>

Which is within the <activity-alias> here </activity-alias> tag.

To extract the meta-data you can get an ActivityInfo from the PackageManager with the TargetActivity:

ActivityInfo appInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), PackageManager.GET_META_DATA);

And extract the meta-data via:

    private static String getAliasNameByMetaData(ActivityInfo app) {
    String aliasName = "";
    if (app.metaData != null && app.metaData.containsKey(ALIAS_META_DATA_KEY)) {
        aliasName = app.metaData.getString(ALIAS_META_DATA_KEY, "");
    } else {
        LOG.i("AliasName by META-DATA didn't work!");
    }
    LOG.v("AliasName by META-DATA: " + aliasName);
    return aliasName;
}

Edit:

Inspecting the Activity class using the debugger, it includes a mActivityInfo field that is different from the ActivityInfo returned by getPackageManager().getActivityInfo() so you can extract it using reflection and check it's name.

Note: It seems that the ActivityInfo returned by getPackageManager().getActivityInfo() is a shallow copy of the mActivityInfo from the Activity. So, maybe this method does not resolve the issue:

Field field = Activity.class.getDeclaredField("mActivityInfo");
field.setAccessible(true);
ActivityInfo value = (ActivityInfo) field.get(this);
Log.e("APPINFO2", "NAME: " + value.name);
antonio
  • 18,044
  • 4
  • 45
  • 61
JacksOnF1re
  • 3,336
  • 24
  • 55
  • how exactly did the meta-data approach fail? – Olayinka Mar 10 '16 at 12:18
  • There were no meta data in the ActivityInfo. – JacksOnF1re Mar 10 '16 at 13:21
  • If you inspect your `targetActivity` on debug, does the `mActivityInfo` field show your Activity or your Alias? – antonio Mar 14 '16 at 12:56
  • For me, on my test device, it shows the alias. In the past I used the mActivityInfo.name to distinguish my aliases. But unfortunately in the wild there are devices where mActivityInfo returns the targetActivity. – JacksOnF1re Mar 14 '16 at 16:51
  • It makes no sense that I post an answer that points to use `mActivity` info to retrieve the name then. I'm editing your question to add this method to improve it if you don't mind – antonio Mar 14 '16 at 16:56
  • Well, I think I already have this one in the question. But yes, edit the question if you think it improves it. Thank you so far! (edit: reflection - i see) – JacksOnF1re Mar 14 '16 at 17:01
  • JacksOnF1re, did you find a solution? I have similar problem, and I'm currently using activity.getComponentName(). Decided to find possible issues, just in case, and found your question. – beetoom Sep 26 '17 at 05:55
  • 1
    You should answer your own question. This would remove the question from the list of unanswered questions and would also probably help others with a similar problem. – David Wasser Mar 27 '18 at 14:10

1 Answers1

0

1. Meta-Data

Unfortunately this method does not work for all devices. If the parsed alias-className from the activity.component returns the target-activity, then the meta-data approach fails, too.

I continued searching for an answer and found a good workaround to distinguish between my aliases inside of the TargetActivty.

You can provide meta-data within your ActivityAlias tag like so:

<activity-alias 
    android:name=".aliasName" 
    android:enabled="false" 
    android:exported="true" 
    android:icon="@drawable/someIconRes" 
    android:label="@string/someLabelRes" android:targetActivity=".yourTargetActivity"> 
    <meta-data android:name="alias" android:value="valueToDistinguish"/>
    <intent-filter>  
        <action android:name="android.intent.action.MAIN"/> 
        <category android:name="android.intent.category.LAUNCHER"/> 
    </intent-filter> 
</activity-alias>

The important part here is:

<meta-data android:name="alias" android:value="valueToDistinguish"/>

Which is within the <activity-alias> here </activity-alias> tag.

To extract the meta-data you can get an ActivityInfo from the PackageManager with the TargetActivity:

ActivityInfo appInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), PackageManager.GET_META_DATA);

And extract the meta-data via:

    private static String getAliasNameByMetaData(ActivityInfo app) {
    String aliasName = "";
    if (app.metaData != null && app.metaData.containsKey(ALIAS_META_DATA_KEY)) {
        aliasName = app.metaData.getString(ALIAS_META_DATA_KEY, "");
    } else {
        LOG.i("AliasName by META-DATA didn't work!");
    }
    LOG.v("AliasName by META-DATA: " + aliasName);
    return aliasName;
}

2. mActivityInfo

Inspecting the Activity class using the debugger, it includes a mActivityInfo field that is different from the ActivityInfo returned by getPackageManager().getActivityInfo() so you can extract it using reflection and check it's name.

Note: It seems that the ActivityInfo returned by getPackageManager().getActivityInfo() is a shallow copy of the mActivityInfo from the Activity. So, maybe this method does not resolve the issue:

Field field = Activity.class.getDeclaredField("mActivityInfo");
field.setAccessible(true);
ActivityInfo value = (ActivityInfo) field.get(this);
Log.e("APPINFO2", "NAME: " + value.name);
JacksOnF1re
  • 3,336
  • 24
  • 55