PackageManager.getLaunchIntentForPackage() returns an intent for LeakLauncherActivity
call PackageManager.getLaunchIntentForPackage()
Activity declaration in AndroidManifest:
<activity
android:name=".LauncherActivity"
android:label="@string/app_name"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Expected behavior:
Should return an Intent for the same Activity as if LeakCanary was not included
N/A
According to the javadoc:
Returns a "good" intent to launch a front-door activity in a package. This is used, for example, to implement an "open" button when browsing through packages. The current implementation looks first for a main activity in the category Intent#CATEGORY_INFO, and next for a main activity in the category Intent#CATEGORY_LAUNCHER. Returns null if neither are found.
AFAIK we need the MAIN action and LAUNCHER category to have the LeakCanary show up in the launcher, right? So I don't think we can really remove that. I'm not sure how getLaunchIntentForPackage() sorts activities, here's the source:
Which lands in this service:
Which goes here: https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/pm/ComponentResolver.java#232
and that's where activities come from: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/pm/PackageParser.java#3850
So, to summarize: the order of activities is based on the order in which they're defined in AndroidManifest.xml, and when looking at activities with LAUNCHER category, getLaunchIntentForPackage takes the first result from queryIntentActivities
So, I don't really see what LeakCanary can do here, although I welcome any idea.
What you could do:
CATEGORY_INFO to your launcher activity, so that it gets picked up first.leak_canary_add_launcher_icon resource bool to false.You don't need MAIN.
Welp, I tried commenting out <action android:name="android.intent.action.MAIN"/> in the intent filter for the activity alias that LeakCanary enables, and the LeakCanary launcher icon disappeared.
Sure looks like I do need MAIN? Suggestions welcome on what to change here to keep a LeakCanary launcher icon.
Oh nevermind it's DEFAULT that you (obviously) don't need. I would expect that flag to be preferred by the API.
Is the LeakCanary launcher icon important? Isn't it sufficient to just have it as an app shortcut?
Dynamic shortcuts aren't supported on older Android versions, they're less discoverable than launcher icons and there's a max so if an app already has app shorcuts LeakCanary won't add its own.
However, see my previous comment, you can always remove the launcher icon for your own app by redefining the leak_canary_add_launcher_icon boolean res to false.
Wouldn't it be better for default behaviour to not have these kind of impacts? So make the launcher icon and shortcuts opt-in rather than opt-out. And the documentation for those flags will then says things like "enabling launcher icon might break getLaunchIntentForPackage" and "shortcut will only display on api 25+ AND if there is sufficient space in shortcuts popup".
We can certainly document the getLaunchIntentForPackage and dynamic shortcut behaviors.
However, changing the default behavior is a much different story.
First, that change would break all users who have come to rely on having the icon in the launcher. A while ago we tried hiding the icon until leaks were found and that created a lot of confusion.
It's been very helpful for LeakCanary to come with its own launcher icon out of the box because most developers won't bother to set up their own entry point from their app. Yes, that means it can break the behavior of getLaunchIntentForPackage but as far as I know the vast majority of devs don't use this. And when you do, there's an easy work around (disable the launcher or add category info).
As a first time user of LeakCanary, I found the presence of a Leaks launcher icon to be confusing. And then when you get multiple launcher icons all called Leaks (I have different flavors in my app as well as different apps/projects) it gets even more confusing as you have to guess which one is for which app. IMO, a better solution would be to have a separate Leaks app that scans the package manager and provides a list of all the apps using LeakCanary.
In terms of a workaround for this issue, could you add an activity alias of CATEGORY_INFO that points to the real launcher activity?
The CATEGORY_INFO flag has to be added to the activity you want picked. So you need to add that to your manifest, to the activity you want.
You can customize the leakcanary icon and label, see the docs.