Home | History | Annotate | Download | only in pm
      1 /**
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.support.v4.content.pm;
     18 
     19 import android.app.Activity;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentSender;
     24 import android.content.pm.PackageManager;
     25 import android.content.pm.ResolveInfo;
     26 import android.content.pm.ShortcutManager;
     27 import android.support.annotation.NonNull;
     28 import android.support.annotation.Nullable;
     29 import android.support.annotation.VisibleForTesting;
     30 import android.support.v4.content.ContextCompat;
     31 import android.support.v4.os.BuildCompat;
     32 import android.text.TextUtils;
     33 
     34 /**
     35  * Helper for accessing features in {@link android.content.pm.ShortcutManager}
     36  * in a backwards compatible fashion.
     37  */
     38 public class ShortcutManagerCompat {
     39 
     40     @VisibleForTesting static final String ACTION_INSTALL_SHORTCUT =
     41             "com.android.launcher.action.INSTALL_SHORTCUT";
     42     @VisibleForTesting static final String INSTALL_SHORTCUT_PERMISSION =
     43             "com.android.launcher.permission.INSTALL_SHORTCUT";
     44 
     45     private ShortcutManagerCompat() {
     46         /* Hide constructor */
     47     }
     48 
     49     /**
     50      * @return {@code true} if the launcher supports {@link #requestPinShortcut},
     51      * {@code false} otherwise
     52      */
     53     public static boolean isRequestPinShortcutSupported(@NonNull Context context) {
     54         if (BuildCompat.isAtLeastO()) {
     55             return context.getSystemService(ShortcutManager.class).isRequestPinShortcutSupported();
     56         }
     57 
     58         if (ContextCompat.checkSelfPermission(context, INSTALL_SHORTCUT_PERMISSION)
     59                 != PackageManager.PERMISSION_GRANTED) {
     60             return false;
     61         }
     62         for (ResolveInfo info : context.getPackageManager().queryBroadcastReceivers(
     63                 new Intent(ACTION_INSTALL_SHORTCUT), 0)) {
     64             String permission = info.activityInfo.permission;
     65             if (TextUtils.isEmpty(permission) || INSTALL_SHORTCUT_PERMISSION.equals(permission)) {
     66                 return true;
     67             }
     68         }
     69         return false;
     70     }
     71 
     72     /**
     73      * Request to create a pinned shortcut.
     74      * <p>On API <= 25 it creates a legacy shortcut with the provided icon, label and intent. For
     75      * newer APIs it will create a {@link android.content.pm.ShortcutInfo} object which can be
     76      * updated by the app.
     77      *
     78      * <p>Use {@link android.app.PendingIntent#getIntentSender()} to create a {@link IntentSender}.
     79      *
     80      * @param shortcut new shortcut to pin
     81      * @param callback if not null, this intent will be sent when the shortcut is pinned
     82      *
     83      * @return {@code true} if the launcher supports this feature
     84      *
     85      * @see #isRequestPinShortcutSupported
     86      * @see IntentSender
     87      * @see android.app.PendingIntent#getIntentSender()
     88      */
     89     public static boolean requestPinShortcut(@NonNull final Context context,
     90             @NonNull ShortcutInfoCompat shortcut, @Nullable final IntentSender callback) {
     91         if (BuildCompat.isAtLeastO()) {
     92             return context.getSystemService(ShortcutManager.class).requestPinShortcut(
     93                     shortcut.toShortcutInfo(), callback);
     94         }
     95 
     96         if (!isRequestPinShortcutSupported(context)) {
     97             return false;
     98         }
     99         Intent intent = shortcut.addToIntent(new Intent(ACTION_INSTALL_SHORTCUT));
    100 
    101         // If the callback is null, just send the broadcast
    102         if (callback == null) {
    103             context.sendBroadcast(intent);
    104             return true;
    105         }
    106 
    107         // Otherwise send the callback when the intent has successfully been dispatched.
    108         context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
    109             @Override
    110             public void onReceive(Context context, Intent intent) {
    111                 try {
    112                     callback.sendIntent(context, 0, null, null, null);
    113                 } catch (IntentSender.SendIntentException e) {
    114                     // Ignore
    115                 }
    116             }
    117         }, null, Activity.RESULT_OK, null, null);
    118         return true;
    119     }
    120 
    121     /**
    122      * Returns an Intent which can be used by the launcher to pin shortcut.
    123      * <p>This should be used by an Activity to set result in response to
    124      * {@link Intent#ACTION_CREATE_SHORTCUT}.
    125      *
    126      * @param shortcut new shortcut to pin
    127      * @return the intent that should be set as the result for the calling activity
    128      *
    129      * @see Intent#ACTION_CREATE_SHORTCUT
    130      */
    131     @NonNull
    132     public static Intent createShortcutResultIntent(@NonNull Context context,
    133             @NonNull ShortcutInfoCompat shortcut) {
    134         Intent result = null;
    135         if (BuildCompat.isAtLeastO()) {
    136             result = context.getSystemService(ShortcutManager.class)
    137                     .createShortcutResultIntent(shortcut.toShortcutInfo());
    138         }
    139         if (result == null) {
    140             result = new Intent();
    141         }
    142         return shortcut.addToIntent(result);
    143     }
    144 }
    145