blob: bd327b0be8748c7c0bebc36bedfe8e69d05feb36 [file] [log] [blame]
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001/*
2 * Copyright (C) 2016 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 */
16package android.content.pm;
17
18import android.annotation.NonNull;
Makoto Onuki2d895c32016-12-02 15:48:40 -080019import android.annotation.Nullable;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080020import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060021import android.annotation.SystemService;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070022import android.annotation.TestApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010023import android.annotation.UnsupportedAppUsage;
Makoto Onukid6e1f3b2016-06-14 11:17:59 -070024import android.annotation.UserIdInt;
Makoto Onukiac042502016-05-20 16:39:42 -070025import android.app.usage.UsageStatsManager;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080026import android.content.ComponentName;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080027import android.content.Context;
Makoto Onuki4a910962016-07-07 13:57:34 -070028import android.content.Intent;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080029import android.content.IntentFilter;
Makoto Onuki2d895c32016-12-02 15:48:40 -080030import android.content.IntentSender;
Makoto Onuki9aeff8a2017-05-30 16:50:20 -070031import android.graphics.drawable.AdaptiveIconDrawable;
Mathew Inwood8c854f82018-09-14 12:35:36 +010032import android.os.Build;
Makoto Onuki16e83d02017-04-17 10:55:21 -070033import android.os.Build.VERSION_CODES;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080034import android.os.Parcel;
35import android.os.Parcelable;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080036import android.os.RemoteException;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070037import android.os.ServiceManager;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080038
39import com.android.internal.annotations.VisibleForTesting;
40
41import java.util.List;
42
43/**
Laura Davisb93f8dd2018-08-07 09:53:52 -070044 * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which
45 * represent specific tasks and actions that users can perform within your app. This page lists
46 * components of the <code>ShortcutManager</code> class that you can use to create and manage
47 * sets of shortcuts.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080048 *
Laura Davisb93f8dd2018-08-07 09:53:52 -070049 * <p>To learn about methods that retrieve information about a single shortcut&mdash;including
50 * identifiers, type, and status&mdash;read the <code>
51 * <a href="/reference/android/content/pm/ShortcutInfo.html">ShortcutInfo</a></code> reference.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080052 *
Laura Davisb93f8dd2018-08-07 09:53:52 -070053 * <p>For guidance about using shortcuts, see
54 * <a href="/guide/topics/ui/shortcuts/index.html">App shortcuts</a>.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080055 *
56 * <h3>Retrieving class instances</h3>
57 * <!-- Provides a heading for the content filled in by the @SystemService annotation below -->
Makoto Onuki6f7362d92016-03-04 13:39:41 -080058 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060059@SystemService(Context.SHORTCUT_SERVICE)
Makoto Onuki6f7362d92016-03-04 13:39:41 -080060public class ShortcutManager {
61 private static final String TAG = "ShortcutManager";
62
63 private final Context mContext;
Mathew Inwood8c854f82018-09-14 12:35:36 +010064 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Makoto Onuki6f7362d92016-03-04 13:39:41 -080065 private final IShortcutService mService;
66
67 /**
68 * @hide
69 */
70 public ShortcutManager(Context context, IShortcutService service) {
71 mContext = context;
72 mService = service;
73 }
74
75 /**
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070076 * @hide
77 */
78 @TestApi
79 public ShortcutManager(Context context) {
80 this(context, IShortcutService.Stub.asInterface(
81 ServiceManager.getService(Context.SHORTCUT_SERVICE)));
82 }
83
84 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -070085 * Publish the list of shortcuts. All existing dynamic shortcuts from the caller app
Makoto Onukife9c9662016-07-25 15:12:23 -070086 * will be replaced. If there are already pinned shortcuts with the same IDs,
87 * the mutable pinned shortcuts are updated.
Makoto Onuki6f7362d92016-03-04 13:39:41 -080088 *
89 * <p>This API will be rate-limited.
90 *
91 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
92 *
Makoto Onuki4a910962016-07-07 13:57:34 -070093 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
Makoto Onukife9c9662016-07-25 15:12:23 -070094 * or when trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -070095 *
96 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -080097 */
98 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
99 try {
100 return mService.setDynamicShortcuts(mContext.getPackageName(),
101 new ParceledListSlice(shortcutInfoList), injectMyUserId());
102 } catch (RemoteException e) {
103 throw e.rethrowFromSystemServer();
104 }
105 }
106
107 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700108 * Return all dynamic shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700109 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700110 * <p>This API is intended to be used for examining what shortcuts are currently published.
111 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
112 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
113 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700114 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800115 */
116 @NonNull
117 public List<ShortcutInfo> getDynamicShortcuts() {
118 try {
119 return mService.getDynamicShortcuts(mContext.getPackageName(), injectMyUserId())
120 .getList();
121 } catch (RemoteException e) {
122 throw e.rethrowFromSystemServer();
123 }
124 }
125
126 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700127 * Return all static (manifest) shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700128 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700129 * <p>This API is intended to be used for examining what shortcuts are currently published.
130 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
131 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
132 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700133 * @throws IllegalStateException when the user is locked.
Makoto Onuki22fcc682016-05-17 14:52:19 -0700134 */
135 @NonNull
136 public List<ShortcutInfo> getManifestShortcuts() {
137 try {
138 return mService.getManifestShortcuts(mContext.getPackageName(), injectMyUserId())
139 .getList();
140 } catch (RemoteException e) {
141 throw e.rethrowFromSystemServer();
142 }
143 }
144
145 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700146 * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with
147 * the same IDs, each mutable shortcut is updated.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800148 *
149 * <p>This API will be rate-limited.
150 *
151 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
152 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700153 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
Makoto Onukife9c9662016-07-25 15:12:23 -0700154 * or when trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700155 *
156 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800157 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700158 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800159 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700160 return mService.addDynamicShortcuts(mContext.getPackageName(),
161 new ParceledListSlice(shortcutInfoList), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800162 } catch (RemoteException e) {
163 throw e.rethrowFromSystemServer();
164 }
165 }
166
167 /**
Makoto Onukic51b2872016-05-04 15:24:50 -0700168 * Delete dynamic shortcuts by ID.
Makoto Onuki9c850012016-07-26 15:50:50 -0700169 *
170 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800171 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700172 public void removeDynamicShortcuts(@NonNull List<String> shortcutIds) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800173 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700174 mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds,
175 injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800176 } catch (RemoteException e) {
177 throw e.rethrowFromSystemServer();
178 }
179 }
180
181 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700182 * Delete all dynamic shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700183 *
184 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800185 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700186 public void removeAllDynamicShortcuts() {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800187 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700188 mService.removeAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800189 } catch (RemoteException e) {
190 throw e.rethrowFromSystemServer();
191 }
192 }
193
194 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700195 * Return all pinned shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700196 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700197 * <p>This API is intended to be used for examining what shortcuts are currently published.
198 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
199 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
200 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700201 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800202 */
203 @NonNull
204 public List<ShortcutInfo> getPinnedShortcuts() {
205 try {
206 return mService.getPinnedShortcuts(mContext.getPackageName(), injectMyUserId())
207 .getList();
208 } catch (RemoteException e) {
209 throw e.rethrowFromSystemServer();
210 }
211 }
212
213 /**
Makoto Onuki4a910962016-07-07 13:57:34 -0700214 * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or
Makoto Onukife9c9662016-07-25 15:12:23 -0700215 * dynamic, but they must not be immutable.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800216 *
217 * <p>This API will be rate-limited.
218 *
219 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
Makoto Onuki4a910962016-07-07 13:57:34 -0700220 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700221 * @throws IllegalArgumentException If trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700222 *
223 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800224 */
Makoto Onuki2d895c32016-12-02 15:48:40 -0800225 public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800226 try {
227 return mService.updateShortcuts(mContext.getPackageName(),
228 new ParceledListSlice(shortcutInfoList), injectMyUserId());
229 } catch (RemoteException e) {
230 throw e.rethrowFromSystemServer();
231 }
232 }
233
234 /**
Laura Davisb93f8dd2018-08-07 09:53:52 -0700235 * Disable pinned shortcuts. For more details, read
236 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
237 * Disable shortcuts</a>.
Makoto Onukife9c9662016-07-25 15:12:23 -0700238 *
239 * @throws IllegalArgumentException If trying to disable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700240 *
241 * @throws IllegalStateException when the user is locked.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700242 */
243 public void disableShortcuts(@NonNull List<String> shortcutIds) {
244 try {
245 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
246 /* disabledMessage =*/ null, /* disabledMessageResId =*/ 0,
247 injectMyUserId());
248 } catch (RemoteException e) {
249 throw e.rethrowFromSystemServer();
250 }
251 }
252
253 /**
Makoto Onukid6880792016-06-29 13:37:43 -0700254 * @hide old signature, kept for unit testing.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700255 */
256 public void disableShortcuts(@NonNull List<String> shortcutIds, int disabledMessageResId) {
257 try {
258 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
259 /* disabledMessage =*/ null, disabledMessageResId,
260 injectMyUserId());
261 } catch (RemoteException e) {
262 throw e.rethrowFromSystemServer();
263 }
264 }
265
266 /**
Makoto Onukid6880792016-06-29 13:37:43 -0700267 * @hide old signature, kept for unit testing.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700268 */
269 public void disableShortcuts(@NonNull List<String> shortcutIds, String disabledMessage) {
Makoto Onukid6880792016-06-29 13:37:43 -0700270 disableShortcuts(shortcutIds, (CharSequence) disabledMessage);
271 }
272
273 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700274 * Disable pinned shortcuts, showing the user a custom error message when they try to select
275 * the disabled shortcuts.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700276 * For more details, read
277 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
278 * Disable shortcuts</a>.
Makoto Onukife9c9662016-07-25 15:12:23 -0700279 *
280 * @throws IllegalArgumentException If trying to disable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700281 *
282 * @throws IllegalStateException when the user is locked.
Makoto Onukid6880792016-06-29 13:37:43 -0700283 */
284 public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) {
Makoto Onuki20c95f82016-05-11 16:51:01 -0700285 try {
286 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
287 disabledMessage, /* disabledMessageResId =*/ 0,
288 injectMyUserId());
289 } catch (RemoteException e) {
290 throw e.rethrowFromSystemServer();
291 }
292 }
293
294 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700295 * Re-enable pinned shortcuts that were previously disabled. If the target shortcuts
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700296 * are already enabled, this method does nothing.
Makoto Onukife9c9662016-07-25 15:12:23 -0700297 *
298 * @throws IllegalArgumentException If trying to enable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700299 *
300 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800301 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700302 public void enableShortcuts(@NonNull List<String> shortcutIds) {
303 try {
304 mService.enableShortcuts(mContext.getPackageName(), shortcutIds, injectMyUserId());
305 } catch (RemoteException e) {
306 throw e.rethrowFromSystemServer();
307 }
308 }
309
Makoto Onukid6880792016-06-29 13:37:43 -0700310
311 /**
312 * @hide old signature, kept for unit testing.
313 */
314 public int getMaxShortcutCountForActivity() {
315 return getMaxShortcutCountPerActivity();
316 }
317
Makoto Onuki22fcc682016-05-17 14:52:19 -0700318 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700319 * Return the maximum number of static and dynamic shortcuts that each launcher icon
Makoto Onuki22fcc682016-05-17 14:52:19 -0700320 * can have at a time.
321 */
Makoto Onukid6880792016-06-29 13:37:43 -0700322 public int getMaxShortcutCountPerActivity() {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800323 try {
Makoto Onukid6880792016-06-29 13:37:43 -0700324 return mService.getMaxShortcutCountPerActivity(
Makoto Onukib5a012f2016-06-21 11:13:53 -0700325 mContext.getPackageName(), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800326 } catch (RemoteException e) {
327 throw e.rethrowFromSystemServer();
328 }
329 }
330
331 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700332 * Return the number of times the caller app can call the rate-limited APIs
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800333 * before the rate limit counter is reset.
334 *
335 * @see #getRateLimitResetTime()
Makoto Onukif805b432016-07-07 11:51:52 -0700336 *
337 * @hide
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800338 */
339 public int getRemainingCallCount() {
340 try {
341 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId());
342 } catch (RemoteException e) {
343 throw e.rethrowFromSystemServer();
344 }
345 }
346
347 /**
348 * Return when the rate limit count will be reset next time, in milliseconds since the epoch.
349 *
350 * @see #getRemainingCallCount()
351 * @see System#currentTimeMillis()
Makoto Onukif805b432016-07-07 11:51:52 -0700352 *
353 * @hide
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800354 */
355 public long getRateLimitResetTime() {
356 try {
357 return mService.getRateLimitResetTime(mContext.getPackageName(), injectMyUserId());
358 } catch (RemoteException e) {
359 throw e.rethrowFromSystemServer();
360 }
361 }
362
Makoto Onuki55046222016-03-08 10:49:47 -0800363 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700364 * Return {@code true} when rate-limiting is active for the caller app.
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700365 *
Laura Davisb93f8dd2018-08-07 09:53:52 -0700366 * <p>For details, see <a href="/guide/topics/ui/shortcuts/managing-shortcuts#rate-limiting">
367 * Rate limiting</a>.
Makoto Onuki9c850012016-07-26 15:50:50 -0700368 *
369 * @throws IllegalStateException when the user is locked.
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700370 */
371 public boolean isRateLimitingActive() {
372 try {
373 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId())
374 == 0;
375 } catch (RemoteException e) {
376 throw e.rethrowFromSystemServer();
377 }
378 }
379
380 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700381 * Return the max width for icons, in pixels.
Hyunyoung Song47037462017-05-08 16:51:43 -0700382 *
383 * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
384 * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700385 * to function as {@link AdaptiveIconDrawable}, multiply
Hyunyoung Song47037462017-05-08 16:51:43 -0700386 * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
Makoto Onuki55046222016-03-08 10:49:47 -0800387 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700388 public int getIconMaxWidth() {
Makoto Onuki55046222016-03-08 10:49:47 -0800389 try {
Makoto Onuki22fcc682016-05-17 14:52:19 -0700390 // TODO Implement it properly using xdpi.
391 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
392 } catch (RemoteException e) {
393 throw e.rethrowFromSystemServer();
394 }
395 }
396
397 /**
398 * Return the max height for icons, in pixels.
399 */
400 public int getIconMaxHeight() {
401 try {
402 // TODO Implement it properly using ydpi.
Makoto Onuki55046222016-03-08 10:49:47 -0800403 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
404 } catch (RemoteException e) {
405 throw e.rethrowFromSystemServer();
406 }
407 }
408
Makoto Onukiac042502016-05-20 16:39:42 -0700409 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700410 * Apps that publish shortcuts should call this method whenever the user
411 * selects the shortcut containing the given ID or when the user completes
412 * an action in the app that is equivalent to selecting the shortcut.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700413 * For more details, read about
414 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#track-usage">
415 * tracking shortcut usage</a>.
Makoto Onukiac042502016-05-20 16:39:42 -0700416 *
417 * <p>The information is accessible via {@link UsageStatsManager#queryEvents}
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700418 * Typically, launcher apps use this information to build a prediction model
Makoto Onukiac042502016-05-20 16:39:42 -0700419 * so that they can promote the shortcuts that are likely to be used at the moment.
Makoto Onuki9c850012016-07-26 15:50:50 -0700420 *
421 * @throws IllegalStateException when the user is locked.
Makoto Onukiac042502016-05-20 16:39:42 -0700422 */
Makoto Onuki20c95f82016-05-11 16:51:01 -0700423 public void reportShortcutUsed(String shortcutId) {
424 try {
425 mService.reportShortcutUsed(mContext.getPackageName(), shortcutId,
426 injectMyUserId());
427 } catch (RemoteException e) {
428 throw e.rethrowFromSystemServer();
429 }
430 }
431
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700432 /**
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700433 * Return {@code TRUE} if the app is running on a device whose default launcher supports
Makoto Onuki2d895c32016-12-02 15:48:40 -0800434 * {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
Makoto Onuki16e83d02017-04-17 10:55:21 -0700435 *
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700436 * <p>The return value may change in subsequent calls if the user changes the default launcher
437 * app.
438 *
439 * <p><b>Note:</b> See also the support library counterpart
440 * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
441 * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
442 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
443 *
444 * @see #requestPinShortcut(ShortcutInfo, IntentSender)
Makoto Onuki2d895c32016-12-02 15:48:40 -0800445 */
446 public boolean isRequestPinShortcutSupported() {
447 try {
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800448 return mService.isRequestPinItemSupported(injectMyUserId(),
449 LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT);
Makoto Onuki2d895c32016-12-02 15:48:40 -0800450 } catch (RemoteException e) {
451 throw e.rethrowFromSystemServer();
452 }
453 }
454
455 /**
456 * Request to create a pinned shortcut. The default launcher will receive this request and
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700457 * ask the user for approval. If the user approves it, the shortcut will be created, and
458 * {@code resultIntent} will be sent. If a request is denied by the user, however, no response
459 * will be sent to the caller.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800460 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700461 * <p>Only apps with a foreground activity or a foreground service can call this method.
462 * Otherwise, it'll throw {@link IllegalStateException}.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800463 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700464 * <p>It's up to the launcher to decide how to handle previous pending requests when the same
465 * package calls this API multiple times in a row. One possible strategy is to ignore any
466 * previous requests.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800467 *
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700468 * <p><b>Note:</b> See also the support library counterpart
469 * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
470 * Context, ShortcutInfoCompat, IntentSender)},
471 * which supports Android versions lower than {@link VERSION_CODES#O} using the
472 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
473 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700474 * @param shortcut Shortcut to pin. If an app wants to pin an existing (either static
475 * or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
476 * to be set, the target shortcut must be enabled.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800477 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700478 * <p>If it's a new shortcut, all the mandatory fields, such as a short label, must be
Makoto Onuki2d895c32016-12-02 15:48:40 -0800479 * set.
480 * @param resultIntent If not null, this intent will be sent when the shortcut is pinned.
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700481 * Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}.
Makoto Onuki16e83d02017-04-17 10:55:21 -0700482 * To avoid background execution limits, use an unexported, manifest-declared receiver.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700483 * For more details, see
484 * <a href="/guide/topics/ui/shortcuts/creating-shortcuts.html#pinned">
485 * Creating pinned shortcuts</a>.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800486 *
487 * @return {@code TRUE} if the launcher supports this feature. Note the API will return without
488 * waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700489 * the shortcut was pinned successfully. {@code FALSE} if the launcher doesn't support this
490 * feature.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800491 *
492 * @see #isRequestPinShortcutSupported()
493 * @see IntentSender
494 * @see android.app.PendingIntent#getIntentSender()
495 *
496 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
497 * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700498 * service, or the device is locked.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800499 */
500 public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
501 @Nullable IntentSender resultIntent) {
502 try {
503 return mService.requestPinShortcut(mContext.getPackageName(), shortcut,
504 resultIntent, injectMyUserId());
505 } catch (RemoteException e) {
506 throw e.rethrowFromSystemServer();
507 }
508 }
509
510 /**
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700511 * Returns an Intent which can be used by the default launcher to pin a shortcut containing the
512 * given {@link ShortcutInfo}. This method should be used by an Activity to set a result in
513 * response to {@link Intent#ACTION_CREATE_SHORTCUT}.
Sunny Goyala6be88a2017-01-12 16:27:58 -0800514 *
515 * @param shortcut New shortcut to pin. If an app wants to pin an existing (either dynamic
516 * or manifest) shortcut, then it only needs to have an ID, and other fields don't have to
517 * be set, in which case, the target shortcut must be enabled.
518 * If it's a new shortcut, all the mandatory fields, such as a short label, must be
519 * set.
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700520 * @return The intent that should be set as the result for the calling activity, or
521 * <code>null</code> if the current launcher doesn't support shortcuts.
Sunny Goyala6be88a2017-01-12 16:27:58 -0800522 *
523 * @see Intent#ACTION_CREATE_SHORTCUT
524 *
525 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
526 */
527 public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
528 try {
529 return mService.createShortcutResultIntent(mContext.getPackageName(), shortcut,
530 injectMyUserId());
531 } catch (RemoteException e) {
532 throw e.rethrowFromSystemServer();
533 }
534 }
535
536 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700537 * Called internally when an app is considered to have come to the foreground
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700538 * even when technically it's not. This method resets the throttling for this package.
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700539 * For example, when the user sends an "inline reply" on a notification, the system UI will
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700540 * call it.
541 *
542 * @hide
543 */
544 public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) {
545 try {
546 mService.onApplicationActive(packageName, userId);
547 } catch (RemoteException e) {
548 throw e.rethrowFromSystemServer();
549 }
550 }
551
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800552 /** @hide injection point */
553 @VisibleForTesting
554 protected int injectMyUserId() {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700555 return mContext.getUserId();
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800556 }
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800557
558 /**
559 * Used by framework's ShareSheet (ChooserActivity.java) to retrieve all of the direct share
560 * targets that match the given IntentFilter.
561 *
562 * @param filter IntentFilter that will be used to retrieve the matching {@link ShortcutInfo}s.
563 * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter.
564 * @hide
565 */
566 @NonNull
567 @SystemApi
568 public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
569 try {
570 return mService.getShareTargets(mContext.getPackageName(), filter,
571 injectMyUserId()).getList();
572 } catch (RemoteException e) {
573 throw e.rethrowFromSystemServer();
574 }
575 }
576
577 /**
578 * Represents the result of a query return by {@link #getShareTargets(IntentFilter)}.
579 *
580 * @hide
581 */
582 @SystemApi
583 public static final class ShareShortcutInfo implements Parcelable {
584 private final ShortcutInfo mShortcutInfo;
585 private final ComponentName mTargetComponent;
586
587 /**
588 * @hide
589 */
590 public ShareShortcutInfo(@NonNull ShortcutInfo shortcutInfo,
591 @NonNull ComponentName targetComponent) {
592 if (shortcutInfo == null) {
593 throw new NullPointerException("shortcut info is null");
594 }
595 if (targetComponent == null) {
596 throw new NullPointerException("target component is null");
597 }
598
599 mShortcutInfo = shortcutInfo;
600 mTargetComponent = targetComponent;
601 }
602
603 private ShareShortcutInfo(Parcel in) {
604 mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
605 mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader());
606 }
607
608 public ShortcutInfo getShortcutInfo() {
609 return mShortcutInfo;
610 }
611
612 public ComponentName getTargetComponent() {
613 return mTargetComponent;
614 }
615
616 @Override
617 public int describeContents() {
618 return 0;
619 }
620
621 @Override
622 public void writeToParcel(Parcel dest, int flags) {
623 dest.writeParcelable(mShortcutInfo, flags);
624 dest.writeParcelable(mTargetComponent, flags);
625 }
626
627 public static final Parcelable.Creator<ShareShortcutInfo> CREATOR =
628 new Parcelable.Creator<ShareShortcutInfo>() {
629 public ShareShortcutInfo createFromParcel(Parcel in) {
630 return new ShareShortcutInfo(in);
631 }
632
633 public ShareShortcutInfo[] newArray(int size) {
634 return new ShareShortcutInfo[size];
635 }
636 };
637 }
Mehdi Alizadeh85fd3d52019-01-23 12:49:53 -0800638
639 /**
640 * Used by framework's ShareSheet (ChooserActivity.java) to check if a given package has share
641 * target definitions in it's resources.
642 *
643 * @param packageName Package to check for share targets.
644 * @return True if the package has any share target definitions, False otherwise.
645 * @hide
646 */
Mehdi Alizadeh627d4db2019-02-04 13:52:03 -0800647 @SystemApi
Mehdi Alizadeh85fd3d52019-01-23 12:49:53 -0800648 public boolean hasShareTargets(@NonNull String packageName) {
649 try {
650 return mService.hasShareTargets(mContext.getPackageName(), packageName,
651 injectMyUserId());
652 } catch (RemoteException e) {
653 throw e.rethrowFromSystemServer();
654 }
655 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800656}