1 /* 2 * Copyright (C) 2012 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 com.android.settings; 18 19 import android.app.Activity; 20 import android.app.ActivityManager; 21 import android.app.LauncherActivity.IconResizer; 22 import android.appwidget.AppWidgetHost; 23 import android.appwidget.AppWidgetManager; 24 import android.appwidget.AppWidgetProviderInfo; 25 import android.content.ActivityNotFoundException; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.PackageManager; 30 import android.content.res.Resources; 31 import android.graphics.Bitmap; 32 import android.graphics.Bitmap.Config; 33 import android.graphics.Canvas; 34 import android.graphics.Paint; 35 import android.graphics.Rect; 36 import android.graphics.drawable.Drawable; 37 import android.os.AsyncTask; 38 import android.os.Bundle; 39 import android.os.IBinder; 40 import android.os.RemoteException; 41 import android.os.ServiceManager; 42 import android.util.DisplayMetrics; 43 import android.util.Log; 44 import android.view.IWindowManager; 45 import android.view.LayoutInflater; 46 import android.view.View; 47 import android.view.ViewGroup; 48 import android.widget.AdapterView; 49 import android.widget.BaseAdapter; 50 import android.widget.GridView; 51 import android.widget.ImageView; 52 import android.widget.TextView; 53 import android.widget.Toast; 54 55 import com.android.internal.widget.LockPatternUtils; 56 57 import java.lang.ref.WeakReference; 58 import java.util.List; 59 60 /** 61 * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any 62 * injected special widgets specified through 63 * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and 64 * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}. 65 * <p> 66 * When an installed {@link AppWidgetProviderInfo} is selected, this activity 67 * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID}, 68 * otherwise it will return the requested extras. 69 */ 70 public class KeyguardAppWidgetPickActivity extends Activity 71 implements GridView.OnItemClickListener, 72 AppWidgetLoader.ItemConstructor<KeyguardAppWidgetPickActivity.Item> { 73 private static final String TAG = "KeyguardAppWidgetPickActivity"; 74 private static final int REQUEST_PICK_APPWIDGET = 126; 75 private static final int REQUEST_CREATE_APPWIDGET = 127; 76 77 private AppWidgetLoader<Item> mAppWidgetLoader; 78 private List<Item> mItems; 79 private GridView mGridView; 80 private AppWidgetAdapter mAppWidgetAdapter; 81 private AppWidgetManager mAppWidgetManager; 82 private int mAppWidgetId; 83 // Might make it possible to make this be false in future 84 private boolean mAddingToKeyguard = true; 85 private Intent mResultData; 86 private LockPatternUtils mLockPatternUtils; 87 private Bundle mExtraConfigureOptions; 88 89 @Override onCreate(Bundle savedInstanceState)90 protected void onCreate(Bundle savedInstanceState) { 91 setContentView(R.layout.keyguard_appwidget_picker_layout); 92 super.onCreate(savedInstanceState); 93 94 // Set default return data 95 setResultData(RESULT_CANCELED, null); 96 97 // Read the appWidgetId passed our direction, otherwise bail if not found 98 final Intent intent = getIntent(); 99 if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) { 100 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 101 AppWidgetManager.INVALID_APPWIDGET_ID); 102 } else { 103 finish(); 104 } 105 mExtraConfigureOptions = intent.getBundleExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS); 106 107 mGridView = (GridView) findViewById(R.id.widget_list); 108 DisplayMetrics dm = new DisplayMetrics(); 109 getWindowManager().getDefaultDisplay().getMetrics(dm); 110 int maxGridWidth = getResources().getDimensionPixelSize( 111 R.dimen.keyguard_appwidget_picker_max_width); 112 113 if (maxGridWidth < dm.widthPixels) { 114 mGridView.getLayoutParams().width = maxGridWidth; 115 } 116 mAppWidgetManager = AppWidgetManager.getInstance(this); 117 mAppWidgetLoader = new AppWidgetLoader<Item>(this, mAppWidgetManager, this); 118 mItems = mAppWidgetLoader.getItems(getIntent()); 119 mAppWidgetAdapter = new AppWidgetAdapter(this, mItems); 120 mGridView.setAdapter(mAppWidgetAdapter); 121 mGridView.setOnItemClickListener(this); 122 123 mLockPatternUtils = new LockPatternUtils(this); // TEMP-- we want to delete this 124 } 125 126 /** 127 * Convenience method for setting the result code and intent. This method 128 * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that 129 * most hosts expect returned. 130 */ setResultData(int code, Intent intent)131 void setResultData(int code, Intent intent) { 132 Intent result = intent != null ? intent : new Intent(); 133 result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); 134 mResultData = result; 135 setResult(code, result); 136 } 137 138 /** 139 * Item that appears in the AppWidget picker grid. 140 */ 141 public static class Item implements AppWidgetLoader.LabelledItem { 142 protected static IconResizer sResizer; 143 144 145 CharSequence label; 146 int appWidgetPreviewId; 147 int iconId; 148 String packageName; 149 String className; 150 Bundle extras; 151 private WidgetPreviewLoader mWidgetPreviewLoader; 152 private Context mContext; 153 154 /** 155 * Create a list item from given label and icon. 156 */ Item(Context context, CharSequence label)157 Item(Context context, CharSequence label) { 158 this.label = label; 159 mContext = context; 160 } 161 loadWidgetPreview(ImageView v)162 void loadWidgetPreview(ImageView v) { 163 mWidgetPreviewLoader = new WidgetPreviewLoader(mContext, v); 164 mWidgetPreviewLoader.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 165 } 166 cancelLoadingWidgetPreview()167 void cancelLoadingWidgetPreview() { 168 if (mWidgetPreviewLoader != null) { 169 mWidgetPreviewLoader.cancel(false); 170 mWidgetPreviewLoader = null; 171 } 172 } 173 174 /** 175 * Build the {@link Intent} described by this item. If this item 176 * can't create a valid {@link android.content.ComponentName}, it will return 177 * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label. 178 */ getIntent()179 Intent getIntent() { 180 Intent intent = new Intent(); 181 if (packageName != null && className != null) { 182 // Valid package and class, so fill details as normal intent 183 intent.setClassName(packageName, className); 184 if (extras != null) { 185 intent.putExtras(extras); 186 } 187 } else { 188 // No valid package or class, so treat as shortcut with label 189 intent.setAction(Intent.ACTION_CREATE_SHORTCUT); 190 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label); 191 } 192 return intent; 193 } 194 getLabel()195 public CharSequence getLabel() { 196 return label; 197 } 198 199 class WidgetPreviewLoader extends AsyncTask<Void, Bitmap, Void> { 200 private Resources mResources; 201 private PackageManager mPackageManager; 202 private int mIconDpi; 203 private ImageView mView; WidgetPreviewLoader(Context context, ImageView v)204 public WidgetPreviewLoader(Context context, ImageView v) { 205 super(); 206 mResources = context.getResources(); 207 mPackageManager = context.getPackageManager(); 208 ActivityManager activityManager = 209 (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 210 mIconDpi = activityManager.getLauncherLargeIconDensity(); 211 mView = v; 212 } doInBackground(Void... params)213 public Void doInBackground(Void... params) { 214 if (!isCancelled()) { 215 int appWidgetPreviewWidth = 216 mResources.getDimensionPixelSize(R.dimen.appwidget_preview_width); 217 int appWidgetPreviewHeight = 218 mResources.getDimensionPixelSize(R.dimen.appwidget_preview_height); 219 Bitmap b = getWidgetPreview(new ComponentName(packageName, className), 220 appWidgetPreviewId, iconId, 221 appWidgetPreviewWidth, appWidgetPreviewHeight); 222 publishProgress(b); 223 } 224 return null; 225 } onProgressUpdate(Bitmap... values)226 public void onProgressUpdate(Bitmap... values) { 227 if (!isCancelled()) { 228 Bitmap b = values[0]; 229 mView.setImageBitmap(b); 230 } 231 } 232 abstract class WeakReferenceThreadLocal<T> { 233 private ThreadLocal<WeakReference<T>> mThreadLocal; WeakReferenceThreadLocal()234 public WeakReferenceThreadLocal() { 235 mThreadLocal = new ThreadLocal<WeakReference<T>>(); 236 } 237 initialValue()238 abstract T initialValue(); 239 set(T t)240 public void set(T t) { 241 mThreadLocal.set(new WeakReference<T>(t)); 242 } 243 get()244 public T get() { 245 WeakReference<T> reference = mThreadLocal.get(); 246 T obj; 247 if (reference == null) { 248 obj = initialValue(); 249 mThreadLocal.set(new WeakReference<T>(obj)); 250 return obj; 251 } else { 252 obj = reference.get(); 253 if (obj == null) { 254 obj = initialValue(); 255 mThreadLocal.set(new WeakReference<T>(obj)); 256 } 257 return obj; 258 } 259 } 260 } 261 262 class CanvasCache extends WeakReferenceThreadLocal<Canvas> { 263 @Override initialValue()264 protected Canvas initialValue() { 265 return new Canvas(); 266 } 267 } 268 269 class PaintCache extends WeakReferenceThreadLocal<Paint> { 270 @Override initialValue()271 protected Paint initialValue() { 272 return null; 273 } 274 } 275 276 class BitmapCache extends WeakReferenceThreadLocal<Bitmap> { 277 @Override initialValue()278 protected Bitmap initialValue() { 279 return null; 280 } 281 } 282 283 class RectCache extends WeakReferenceThreadLocal<Rect> { 284 @Override initialValue()285 protected Rect initialValue() { 286 return new Rect(); 287 } 288 } 289 290 // Used for drawing widget previews 291 CanvasCache sCachedAppWidgetPreviewCanvas = new CanvasCache(); 292 RectCache sCachedAppWidgetPreviewSrcRect = new RectCache(); 293 RectCache sCachedAppWidgetPreviewDestRect = new RectCache(); 294 PaintCache sCachedAppWidgetPreviewPaint = new PaintCache(); 295 getWidgetPreview(ComponentName provider, int previewImage, int iconId, int maxWidth, int maxHeight)296 private Bitmap getWidgetPreview(ComponentName provider, int previewImage, 297 int iconId, int maxWidth, int maxHeight) { 298 // Load the preview image if possible 299 String packageName = provider.getPackageName(); 300 if (maxWidth < 0) maxWidth = Integer.MAX_VALUE; 301 if (maxHeight < 0) maxHeight = Integer.MAX_VALUE; 302 303 304 int appIconSize = mResources.getDimensionPixelSize(R.dimen.app_icon_size); 305 306 Drawable drawable = null; 307 if (previewImage != 0) { 308 drawable = mPackageManager.getDrawable(packageName, previewImage, null); 309 if (drawable == null) { 310 Log.w(TAG, "Can't load widget preview drawable 0x" + 311 Integer.toHexString(previewImage) + " for provider: " + provider); 312 } 313 } 314 315 int bitmapWidth; 316 int bitmapHeight; 317 Bitmap defaultPreview = null; 318 boolean widgetPreviewExists = (drawable != null); 319 if (widgetPreviewExists) { 320 bitmapWidth = drawable.getIntrinsicWidth(); 321 bitmapHeight = drawable.getIntrinsicHeight(); 322 } else { 323 // Generate a preview image if we couldn't load one 324 bitmapWidth = appIconSize; 325 bitmapHeight = appIconSize; 326 defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, 327 Config.ARGB_8888); 328 329 try { 330 Drawable icon = null; 331 if (iconId > 0) 332 icon = getFullResIcon(packageName, iconId); 333 if (icon != null) { 334 renderDrawableToBitmap(icon, defaultPreview, 0, 335 0, appIconSize, appIconSize); 336 } 337 } catch (Resources.NotFoundException e) { 338 } 339 } 340 341 // Scale to fit width only - let the widget preview be clipped in the 342 // vertical dimension 343 float scale = 1f; 344 if (bitmapWidth > maxWidth) { 345 scale = maxWidth / (float) bitmapWidth; 346 } 347 int finalPreviewWidth = (int) (scale * bitmapWidth); 348 int finalPreviewHeight = (int) (scale * bitmapHeight); 349 350 bitmapWidth = finalPreviewWidth; 351 bitmapHeight = Math.min(finalPreviewHeight, maxHeight); 352 353 Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, 354 Config.ARGB_8888); 355 356 // Draw the scaled preview into the final bitmap 357 if (widgetPreviewExists) { 358 renderDrawableToBitmap(drawable, preview, 0, 0, finalPreviewWidth, 359 finalPreviewHeight); 360 } else { 361 final Canvas c = sCachedAppWidgetPreviewCanvas.get(); 362 final Rect src = sCachedAppWidgetPreviewSrcRect.get(); 363 final Rect dest = sCachedAppWidgetPreviewDestRect.get(); 364 c.setBitmap(preview); 365 src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight()); 366 dest.set(0, 0, finalPreviewWidth, finalPreviewHeight); 367 368 Paint p = sCachedAppWidgetPreviewPaint.get(); 369 if (p == null) { 370 p = new Paint(); 371 p.setFilterBitmap(true); 372 sCachedAppWidgetPreviewPaint.set(p); 373 } 374 c.drawBitmap(defaultPreview, src, dest, p); 375 c.setBitmap(null); 376 } 377 return preview; 378 } getFullResDefaultActivityIcon()379 public Drawable getFullResDefaultActivityIcon() { 380 return getFullResIcon(Resources.getSystem(), 381 android.R.mipmap.sym_def_app_icon); 382 } 383 getFullResIcon(Resources resources, int iconId)384 public Drawable getFullResIcon(Resources resources, int iconId) { 385 Drawable d; 386 try { 387 d = resources.getDrawableForDensity(iconId, mIconDpi); 388 } catch (Resources.NotFoundException e) { 389 d = null; 390 } 391 392 return (d != null) ? d : getFullResDefaultActivityIcon(); 393 } 394 getFullResIcon(String packageName, int iconId)395 public Drawable getFullResIcon(String packageName, int iconId) { 396 Resources resources; 397 try { 398 resources = mPackageManager.getResourcesForApplication(packageName); 399 } catch (PackageManager.NameNotFoundException e) { 400 resources = null; 401 } 402 if (resources != null) { 403 if (iconId != 0) { 404 return getFullResIcon(resources, iconId); 405 } 406 } 407 return getFullResDefaultActivityIcon(); 408 } 409 renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h)410 private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) { 411 renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f); 412 } 413 renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h, float scale)414 private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h, 415 float scale) { 416 if (bitmap != null) { 417 Canvas c = new Canvas(bitmap); 418 c.scale(scale, scale); 419 Rect oldBounds = d.copyBounds(); 420 d.setBounds(x, y, x + w, y + h); 421 d.draw(c); 422 d.setBounds(oldBounds); // Restore the bounds 423 c.setBitmap(null); 424 } 425 } 426 } 427 } 428 429 @Override createItem(Context context, AppWidgetProviderInfo info, Bundle extras)430 public Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) { 431 CharSequence label = info.label; 432 433 Item item = new Item(context, label); 434 item.appWidgetPreviewId = info.previewImage; 435 item.iconId = info.icon; 436 item.packageName = info.provider.getPackageName(); 437 item.className = info.provider.getClassName(); 438 item.extras = extras; 439 return item; 440 } 441 442 protected static class AppWidgetAdapter extends BaseAdapter { 443 private final LayoutInflater mInflater; 444 private final List<Item> mItems; 445 446 /** 447 * Create an adapter for the given items. 448 */ AppWidgetAdapter(Context context, List<Item> items)449 public AppWidgetAdapter(Context context, List<Item> items) { 450 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 451 mItems = items; 452 } 453 454 /** 455 * {@inheritDoc} 456 */ getCount()457 public int getCount() { 458 return mItems.size(); 459 } 460 461 /** 462 * {@inheritDoc} 463 */ getItem(int position)464 public Object getItem(int position) { 465 return mItems.get(position); 466 } 467 468 /** 469 * {@inheritDoc} 470 */ getItemId(int position)471 public long getItemId(int position) { 472 return position; 473 } 474 475 /** 476 * {@inheritDoc} 477 */ getView(int position, View convertView, ViewGroup parent)478 public View getView(int position, View convertView, ViewGroup parent) { 479 if (convertView == null) { 480 convertView = mInflater.inflate(R.layout.keyguard_appwidget_item, parent, false); 481 } 482 483 Item item = (Item) getItem(position); 484 TextView textView = (TextView) convertView.findViewById(R.id.label); 485 textView.setText(item.label); 486 ImageView iconView = (ImageView) convertView.findViewById(R.id.icon); 487 iconView.setImageDrawable(null); 488 item.loadWidgetPreview(iconView); 489 return convertView; 490 } 491 cancelAllWidgetPreviewLoaders()492 public void cancelAllWidgetPreviewLoaders() { 493 for (int i = 0; i < mItems.size(); i++) { 494 mItems.get(i).cancelLoadingWidgetPreview(); 495 } 496 } 497 } 498 499 /** 500 * {@inheritDoc} 501 */ 502 @Override onItemClick(AdapterView<?> parent, View view, int position, long id)503 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 504 Item item = mItems.get(position); 505 Intent intent = item.getIntent(); 506 507 int result; 508 if (item.extras != null) { 509 // If these extras are present it's because this entry is custom. 510 // Don't try to bind it, just pass it back to the app. 511 result = RESULT_OK; 512 setResultData(result, intent); 513 } else { 514 try { 515 if (mAddingToKeyguard && mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { 516 // Found in KeyguardHostView.java 517 final int KEYGUARD_HOST_ID = 0x4B455947; 518 mAppWidgetId = AppWidgetHost.allocateAppWidgetIdForSystem(KEYGUARD_HOST_ID); 519 } 520 mAppWidgetManager.bindAppWidgetId( 521 mAppWidgetId, intent.getComponent(), mExtraConfigureOptions); 522 result = RESULT_OK; 523 } catch (IllegalArgumentException e) { 524 // This is thrown if they're already bound, or otherwise somehow 525 // bogus. Set the result to canceled, and exit. The app *should* 526 // clean up at this point. We could pass the error along, but 527 // it's not clear that that's useful -- the widget will simply not 528 // appear. 529 result = RESULT_CANCELED; 530 } 531 setResultData(result, null); 532 } 533 if (mAddingToKeyguard) { 534 onActivityResult(REQUEST_PICK_APPWIDGET, result, mResultData); 535 } else { 536 finish(); 537 } 538 } 539 onDestroy()540 protected void onDestroy() { 541 if (mAppWidgetAdapter != null) { 542 mAppWidgetAdapter.cancelAllWidgetPreviewLoaders(); 543 } 544 super.onDestroy(); 545 } 546 547 @Override onActivityResult(int requestCode, int resultCode, Intent data)548 public void onActivityResult(int requestCode, int resultCode, Intent data) { 549 super.onActivityResult(requestCode, resultCode, data); 550 if (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET) { 551 int appWidgetId; 552 if (data == null) { 553 appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID ; 554 } else { 555 appWidgetId = data.getIntExtra( 556 AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); 557 } 558 if (requestCode == REQUEST_PICK_APPWIDGET && resultCode == Activity.RESULT_OK) { 559 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this); 560 561 AppWidgetProviderInfo appWidget = null; 562 appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId); 563 564 if (appWidget.configure != null) { 565 // Launch over to configure widget, if needed 566 Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); 567 intent.setComponent(appWidget.configure); 568 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 569 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 570 571 startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET); 572 } else { 573 // Otherwise just add it 574 onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); 575 } 576 } else if (requestCode == REQUEST_CREATE_APPWIDGET && resultCode == Activity.RESULT_OK) { 577 mLockPatternUtils.addAppWidget(appWidgetId, 0); 578 finishDelayedAndShowLockScreen(appWidgetId); 579 } else { 580 if (mAddingToKeyguard && 581 mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { 582 AppWidgetHost.deleteAppWidgetIdForSystem(mAppWidgetId); 583 } 584 finishDelayedAndShowLockScreen(AppWidgetManager.INVALID_APPWIDGET_ID); 585 } 586 } 587 } 588 finishDelayedAndShowLockScreen(int appWidgetId)589 private void finishDelayedAndShowLockScreen(int appWidgetId) { 590 IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE); 591 IWindowManager iWm = IWindowManager.Stub.asInterface(b); 592 Bundle opts = null; 593 if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { 594 opts = new Bundle(); 595 opts.putInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET, appWidgetId); 596 } 597 try { 598 iWm.lockNow(opts); 599 } catch (RemoteException e) { 600 } 601 602 // Change background to all black 603 ViewGroup root = (ViewGroup) findViewById(R.id.layout_root); 604 root.setBackgroundColor(0xFF000000); 605 // Hide all children 606 final int childCount = root.getChildCount(); 607 for (int i = 0; i < childCount; i++) { 608 root.getChildAt(i).setVisibility(View.INVISIBLE); 609 } 610 mGridView.postDelayed(new Runnable() { 611 public void run() { 612 finish(); 613 } 614 }, 500); 615 } 616 startActivityForResultSafely(Intent intent, int requestCode)617 void startActivityForResultSafely(Intent intent, int requestCode) { 618 try { 619 startActivityForResult(intent, requestCode); 620 } catch (ActivityNotFoundException e) { 621 Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); 622 } catch (SecurityException e) { 623 Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); 624 Log.e(TAG, "Settings does not have the permission to launch " + intent, e); 625 } 626 } 627 } 628