/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM; import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserIdInt; import android.annotation.WorkerThread; import android.app.Notification; import android.app.usage.UsageStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.graphics.drawable.AdaptiveIconDrawable; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.infra.AndroidFuture; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.concurrent.ExecutionException; /** *
ShortcutManager
executes operations on an app's set of shortcuts, which
* represent specific tasks and actions that users can perform within your app. This page lists
* components of the ShortcutManager
class that you can use to create and manage
* sets of shortcuts.
*
*
To learn about methods that retrieve information about a single shortcut—including
* identifiers, type, and status—read the
* ShortcutInfo
reference.
*
*
For guidance about using shortcuts, see * App shortcuts. * *
This API will be rate-limited.
*
* @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
*
* @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
* or when trying to update immutable shortcuts.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
public boolean setDynamicShortcuts(@NonNull List This API is intended to be used for examining what shortcuts are currently published.
* Re-publishing returned {@link ShortcutInfo}s via APIs such as
* {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
@NonNull
public List This API is intended to be used for examining what shortcuts are currently published.
* Re-publishing returned {@link ShortcutInfo}s via APIs such as
* {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
@NonNull
public List At least one of the {@code MATCH} flags should be set. Otherwise no shortcuts will be
* returned.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
@NonNull
public List This API will be rate-limited.
*
* @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
*
* @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
* or when trying to update immutable shortcuts.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
public boolean addDynamicShortcuts(@NonNull List This API is intended to be used for examining what shortcuts are currently published.
* Re-publishing returned {@link ShortcutInfo}s via APIs such as
* {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
@NonNull
public List This API will be rate-limited.
*
* @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
*
* @throws IllegalArgumentException If trying to update immutable shortcuts.
*
* @throws IllegalStateException when the user is locked.
*/
@WorkerThread
public boolean updateShortcuts(@NonNull List For details, see
* Rate limiting.
*
* @throws IllegalStateException when the user is locked.
*/
public boolean isRateLimitingActive() {
try {
return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId())
== 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return the max width for icons, in pixels.
*
* Note that this method returns max width of icon's visible part. Hence, it does not take
* into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
* to function as {@link AdaptiveIconDrawable}, multiply
* 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
*/
public int getIconMaxWidth() {
try {
// TODO Implement it properly using xdpi.
return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return the max height for icons, in pixels.
*/
public int getIconMaxHeight() {
try {
// TODO Implement it properly using ydpi.
return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Apps that publish shortcuts should call this method whenever the user
* selects the shortcut containing the given ID or when the user completes
* an action in the app that is equivalent to selecting the shortcut.
* For more details, read about
*
* tracking shortcut usage.
*
* The information is accessible via {@link UsageStatsManager#queryEvents}
* Typically, launcher apps use this information to build a prediction model
* so that they can promote the shortcuts that are likely to be used at the moment.
*
* @throws IllegalStateException when the user is locked.
*/
public void reportShortcutUsed(String shortcutId) {
try {
mService.reportShortcutUsed(mContext.getPackageName(), shortcutId, injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return {@code TRUE} if the app is running on a device whose default launcher supports
* {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
*
* The return value may change in subsequent calls if the user changes the default launcher
* app.
*
* Note: See also the support library counterpart
* {@link androidx.core.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
* Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
* legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
*
* @see #requestPinShortcut(ShortcutInfo, IntentSender)
*/
public boolean isRequestPinShortcutSupported() {
try {
return mService.isRequestPinItemSupported(injectMyUserId(),
LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request to create a pinned shortcut. The default launcher will receive this request and
* ask the user for approval. If the user approves it, the shortcut will be created, and
* {@code resultIntent} will be sent. If a request is denied by the user, however, no response
* will be sent to the caller.
*
* Only apps with a foreground activity or a foreground service can call this method.
* Otherwise, it'll throw {@link IllegalStateException}.
*
* It's up to the launcher to decide how to handle previous pending requests when the same
* package calls this API multiple times in a row. One possible strategy is to ignore any
* previous requests.
*
* Note: See also the support library counterpart
* {@link androidx.core.content.pm.ShortcutManagerCompat#requestPinShortcut(
* Context, ShortcutInfoCompat, IntentSender)},
* which supports Android versions lower than {@link VERSION_CODES#O} using the
* legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
*
* @param shortcut Shortcut to pin. If an app wants to pin an existing (either static
* or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
* to be set, the target shortcut must be enabled.
*
* If it's a new shortcut, all the mandatory fields, such as a short label, must be
* set.
* @param resultIntent If not null, this intent will be sent when the shortcut is pinned.
* Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}.
* To avoid background execution limits, use an unexported, manifest-declared receiver.
* For more details, see
*
* Creating pinned shortcuts.
*
* @return {@code TRUE} if the launcher supports this feature. Note the API will return without
* waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
* the shortcut was pinned successfully. {@code FALSE} if the launcher doesn't support this
* feature or if calling app belongs to a user-profile with items restricted on home screen.
*
* @see #isRequestPinShortcutSupported()
* @see IntentSender
* @see android.app.PendingIntent#getIntentSender()
*
* @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
* @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
* service, or the device is locked.
*/
@WorkerThread
public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
@Nullable IntentSender resultIntent) {
try {
AndroidFuture This method is useful when posting notifications which are tagged with shortcut IDs; In
* order to make sure shortcuts exist and are up-to-date, without the need to explicitly handle
* the shortcut count limit.
* @see android.app.NotificationManager#notify(int, Notification)
* @see android.app.Notification.Builder#setShortcutId(String)
*
* If {@link #getMaxShortcutCountPerActivity()} is already reached, an existing shortcut with
* the lowest rank will be removed to add space for the new shortcut.
*
* If the rank of the shortcut is not explicitly set, it will be set to zero, and shortcut
* will be added to the top of the list.
*
* @throws IllegalArgumentException if trying to update an immutable shortcut.
*
* @throws IllegalStateException when the user is locked.
*/
public void pushDynamicShortcut(@NonNull ShortcutInfo shortcut) {
try {
mService.pushDynamicShortcut(mContext.getPackageName(), shortcut, injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private static
*
* @return list of {@link ShortcutInfo}s that match the flag.
*
* null
if the current launcher doesn't support shortcuts.
*
* @see Intent#ACTION_CREATE_SHORTCUT
*
* @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
*/
@WorkerThread
public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
final AndroidFuture