How to create shortcuts on Android O, when targett

2019-04-29 09:32发布

问题:

Background

Android O has various changes of how shortcuts work:

https://developer.android.com/preview/behavior-changes.html#as

The problem

According to recent changes on Android O, the broadcast intent to create shortcuts is completely ignored :

https://developer.android.com/reference/android/content/Intent.html#ACTION_CREATE_SHORTCUT https://developer.android.com/preview/behavior-changes.html#as

The com.android.launcher.action.INSTALL_SHORTCUT broadcast no longer has any effect on your app, because it is now a private, implicit broadcast. Instead, you should create an app shortcut by using the requestPinShortcut() method from the ShortcutManager class.

This means this code, for example, won't work anymore, no matter which app you've made or which launcher the user has:

private void addShortcut(@NonNull final Context context) {
    Intent intent = new Intent().putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(context, MainActivity.class).setAction(Intent.ACTION_MAIN))
            .putExtra(Intent.EXTRA_SHORTCUT_NAME, "HelloWorldShortcut")
            .putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, ShortcutIconResource.fromContext(context, R.mipmap.ic_launcher))
            .setAction("com.android.launcher.action.INSTALL_SHORTCUT");
    context.sendBroadcast(intent);
}

Currently, even the Play Store itself fails to create shortcuts to apps (at least in the current version: 80795200 ) . It just doesn't do anything, even to Google's launcher.

The question

While I'm very against this change of API (and wrote about it here, here) and here, I'd like to know what would it take to still make it work.

I know there is an API for this, using requestPinShortcut, but this requires the app to target Android O, which means a lot more changes have to be made to make sure the app works there.

My question is: Suppose your app targets Android API 25, how do you create shortcuts on Android O ? Is it possible by using reflection of the newer API ? If so, how?

回答1:

The right way is to call requestPinShortcut method. You don't need to target android O but you need to have at least compile SDK to 26. Compile SDK and target SDK are two different things.



回答2:

It seems like I beat on this forever, but...

if(Build.VERSION.SDK_INT < 26) {
    ...
}
else {
    ShortcutManager shortcutManager
        = c.getSystemService(ShortcutManager.class);
    if (shortcutManager.isRequestPinShortcutSupported()) {
        Intent intent = new Intent(
            c.getApplicationContext(), c.getClass());
        intent.setAction(Intent.ACTION_MAIN);
        ShortcutInfo pinShortcutInfo = new ShortcutInfo
            .Builder(c,"pinned-shortcut")
            .setIcon(
                Icon.createWithResource(c, R.drawable.qmark)
            )
            .setIntent(intent)
            .setShortLabel(c.getString(R.string.app_label))
            .build();
        Intent pinnedShortcutCallbackIntent = shortcutManager
            .createShortcutResultIntent(pinShortcutInfo);
        //Get notified when a shortcut is pinned successfully//
        PendingIntent successCallback
            = PendingIntent.getBroadcast(
                c, 0
                , pinnedShortcutCallbackIntent, 0
            );
        shortcutManager.requestPinShortcut(
            pinShortcutInfo, successCallback.getIntentSender()
        );
    }
}

Is working for me. I know there were changes in 7.1 and don't know if this works for them and I don't know about the launcher issues mentioned above.
This was tested on a Samsung Galaxy Tab S3 running Android 8.0.0.

I put a simple app that does nothing but install a shortcut for itself on your homepage on github. It works for versions before and after Android 8. Pre Android 8 uses the sendBroadcast method and after creats a pinned shortcut.