1 /* 2 * Copyright (C) 2015 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 package com.android.messaging.ui; 17 18 import android.app.Activity; 19 import android.app.Fragment; 20 import android.app.PendingIntent; 21 import android.appwidget.AppWidgetManager; 22 import android.content.ActivityNotFoundException; 23 import android.content.ClipData; 24 import android.content.ComponentName; 25 import android.content.ContentValues; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.graphics.Point; 29 import android.graphics.Rect; 30 import android.media.RingtoneManager; 31 import android.net.Uri; 32 import android.os.Bundle; 33 import android.provider.ContactsContract.Contacts; 34 import android.provider.ContactsContract.Intents; 35 import android.provider.MediaStore; 36 import android.provider.Telephony; 37 import androidx.annotation.Nullable; 38 import androidx.core.app.TaskStackBuilder; 39 import androidx.localbroadcastmanager.content.LocalBroadcastManager; 40 import android.text.TextUtils; 41 42 import com.android.ex.photo.Intents.PhotoViewIntentBuilder; 43 import com.android.messaging.R; 44 import com.android.messaging.datamodel.ConversationImagePartsView; 45 import com.android.messaging.datamodel.MediaScratchFileProvider; 46 import com.android.messaging.datamodel.MessagingContentProvider; 47 import com.android.messaging.datamodel.data.MessageData; 48 import com.android.messaging.datamodel.data.MessagePartData; 49 import com.android.messaging.datamodel.data.ParticipantData; 50 import com.android.messaging.receiver.NotificationReceiver; 51 import com.android.messaging.sms.MmsSmsUtils; 52 import com.android.messaging.ui.appsettings.ApnEditorActivity; 53 import com.android.messaging.ui.appsettings.ApnSettingsActivity; 54 import com.android.messaging.ui.appsettings.ApplicationSettingsActivity; 55 import com.android.messaging.ui.appsettings.PerSubscriptionSettingsActivity; 56 import com.android.messaging.ui.appsettings.SettingsActivity; 57 import com.android.messaging.ui.attachmentchooser.AttachmentChooserActivity; 58 import com.android.messaging.ui.conversation.ConversationActivity; 59 import com.android.messaging.ui.conversation.LaunchConversationActivity; 60 import com.android.messaging.ui.conversationlist.ArchivedConversationListActivity; 61 import com.android.messaging.ui.conversationlist.ConversationListActivity; 62 import com.android.messaging.ui.conversationlist.ForwardMessageActivity; 63 import com.android.messaging.ui.conversationsettings.PeopleAndOptionsActivity; 64 import com.android.messaging.ui.debug.DebugMmsConfigActivity; 65 import com.android.messaging.ui.photoviewer.BuglePhotoViewActivity; 66 import com.android.messaging.util.Assert; 67 import com.android.messaging.util.ContentType; 68 import com.android.messaging.util.ConversationIdSet; 69 import com.android.messaging.util.LogUtil; 70 import com.android.messaging.util.UiUtils; 71 import com.android.messaging.util.UriUtil; 72 73 /** 74 * A central repository of Intents used to start activities. 75 */ 76 public class UIIntentsImpl extends UIIntents { 77 private static final String CELL_BROADCAST_LIST_ACTIVITY = 78 "com.android.cellbroadcastreceiver.CellBroadcastListActivity"; 79 private static final String CALL_TARGET_CLICK_KEY = "touchPoint"; 80 private static final String CALL_TARGET_CLICK_EXTRA_KEY = 81 "android.telecom.extra.OUTGOING_CALL_EXTRAS"; 82 private static final String MEDIA_SCANNER_CLASS = 83 "com.android.providers.media.MediaScannerService"; 84 private static final String MEDIA_SCANNER_PACKAGE = "com.android.providers.media"; 85 private static final String MEDIA_SCANNER_SCAN_ACTION = "android.media.IMediaScannerService"; 86 87 /** 88 * Get an intent which takes you to a conversation 89 */ getConversationActivityIntent(final Context context, final String conversationId, final MessageData draft, final boolean withCustomTransition)90 private Intent getConversationActivityIntent(final Context context, 91 final String conversationId, final MessageData draft, 92 final boolean withCustomTransition) { 93 final Intent intent = new Intent(context, ConversationActivity.class); 94 95 // Always try to reuse the same ConversationActivity in the current task so that we don't 96 // have two conversation activities in the back stack. 97 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 98 99 // Otherwise we're starting a new conversation 100 if (conversationId != null) { 101 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId); 102 } 103 if (draft != null) { 104 intent.putExtra(UI_INTENT_EXTRA_DRAFT_DATA, draft); 105 106 // If draft attachments came from an external content provider via a share intent, we 107 // need to propagate the URI permissions through to ConversationActivity. This requires 108 // putting the URIs into the ClipData (setData also works, but accepts only one URI). 109 ClipData clipData = null; 110 for (final MessagePartData partData : draft.getParts()) { 111 if (partData.isAttachment()) { 112 final Uri uri = partData.getContentUri(); 113 if (clipData == null) { 114 clipData = ClipData.newRawUri("Attachments", uri); 115 } else { 116 clipData.addItem(new ClipData.Item(uri)); 117 } 118 } 119 } 120 if (clipData != null) { 121 intent.setClipData(clipData); 122 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 123 } 124 } 125 if (withCustomTransition) { 126 intent.putExtra(UI_INTENT_EXTRA_WITH_CUSTOM_TRANSITION, true); 127 } 128 129 if (!(context instanceof Activity)) { 130 // If the caller supplies an application context, and not an activity context, we must 131 // include this flag 132 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 133 } 134 return intent; 135 } 136 137 @Override launchPermissionCheckActivity(final Context context)138 public void launchPermissionCheckActivity(final Context context) { 139 final Intent intent = new Intent(context, PermissionCheckActivity.class); 140 context.startActivity(intent); 141 } 142 143 /** 144 * Get an intent which takes you to the conversation list 145 */ getConversationListActivityIntent(final Context context)146 private Intent getConversationListActivityIntent(final Context context) { 147 return new Intent(context, ConversationListActivity.class); 148 } 149 150 @Override launchConversationListActivity(final Context context)151 public void launchConversationListActivity(final Context context) { 152 final Intent intent = getConversationListActivityIntent(context); 153 context.startActivity(intent); 154 } 155 156 /** 157 * Get an intent which shows the low storage warning activity. 158 */ getSmsStorageLowWarningActivityIntent(final Context context)159 private Intent getSmsStorageLowWarningActivityIntent(final Context context) { 160 return new Intent(context, SmsStorageLowWarningActivity.class); 161 } 162 163 @Override launchConversationActivity(final Context context, final String conversationId, final MessageData draft, final Bundle activityOptions, final boolean withCustomTransition)164 public void launchConversationActivity(final Context context, 165 final String conversationId, final MessageData draft, final Bundle activityOptions, 166 final boolean withCustomTransition) { 167 Assert.isTrue(!withCustomTransition || activityOptions != null); 168 final Intent intent = getConversationActivityIntent(context, conversationId, draft, 169 withCustomTransition); 170 context.startActivity(intent, activityOptions); 171 } 172 173 @Override launchConversationActivityNewTask( final Context context, final String conversationId)174 public void launchConversationActivityNewTask( 175 final Context context, final String conversationId) { 176 final Intent intent = getConversationActivityIntent(context, conversationId, null, 177 false /* withCustomTransition */); 178 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 179 context.startActivity(intent); 180 } 181 182 @Override launchConversationActivityWithParentStack(final Context context, final String conversationId, final String smsBody)183 public void launchConversationActivityWithParentStack(final Context context, 184 final String conversationId, final String smsBody) { 185 final MessageData messageData = TextUtils.isEmpty(smsBody) 186 ? null 187 : MessageData.createDraftSmsMessage(conversationId, null, smsBody); 188 TaskStackBuilder.create(context) 189 .addNextIntentWithParentStack( 190 getConversationActivityIntent(context, conversationId, messageData, 191 false /* withCustomTransition */)) 192 .startActivities(); 193 } 194 195 @Override launchCreateNewConversationActivity(final Context context, final MessageData draft)196 public void launchCreateNewConversationActivity(final Context context, 197 final MessageData draft) { 198 final Intent intent = getConversationActivityIntent(context, null, draft, 199 false /* withCustomTransition */); 200 context.startActivity(intent); 201 } 202 203 @Override launchDebugMmsConfigActivity(final Context context)204 public void launchDebugMmsConfigActivity(final Context context) { 205 context.startActivity(new Intent(context, DebugMmsConfigActivity.class)); 206 } 207 208 @Override launchAddContactActivity(final Context context, final String destination)209 public void launchAddContactActivity(final Context context, final String destination) { 210 final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 211 final String destinationType = MmsSmsUtils.isEmailAddress(destination) ? 212 Intents.Insert.EMAIL : Intents.Insert.PHONE; 213 intent.setType(Contacts.CONTENT_ITEM_TYPE); 214 intent.putExtra(destinationType, destination); 215 startExternalActivity(context, intent); 216 } 217 218 @Override launchSettingsActivity(final Context context)219 public void launchSettingsActivity(final Context context) { 220 final Intent intent = new Intent(context, SettingsActivity.class); 221 context.startActivity(intent); 222 } 223 224 @Override launchArchivedConversationsActivity(final Context context)225 public void launchArchivedConversationsActivity(final Context context) { 226 final Intent intent = new Intent(context, ArchivedConversationListActivity.class); 227 context.startActivity(intent); 228 } 229 230 @Override launchBlockedParticipantsActivity(final Context context)231 public void launchBlockedParticipantsActivity(final Context context) { 232 final Intent intent = new Intent(context, BlockedParticipantsActivity.class); 233 context.startActivity(intent); 234 } 235 236 @Override launchDocumentImagePicker(final Fragment fragment)237 public void launchDocumentImagePicker(final Fragment fragment) { 238 final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 239 intent.putExtra(Intent.EXTRA_MIME_TYPES, MessagePartData.ACCEPTABLE_IMAGE_TYPES); 240 intent.addCategory(Intent.CATEGORY_OPENABLE); 241 intent.setType(ContentType.IMAGE_UNSPECIFIED); 242 243 fragment.startActivityForResult(intent, REQUEST_PICK_IMAGE_FROM_DOCUMENT_PICKER); 244 } 245 246 @Override launchPeopleAndOptionsActivity(final Activity activity, final String conversationId)247 public void launchPeopleAndOptionsActivity(final Activity activity, 248 final String conversationId) { 249 final Intent intent = new Intent(activity, PeopleAndOptionsActivity.class); 250 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId); 251 activity.startActivityForResult(intent, 0); 252 } 253 254 @Override launchPhoneCallActivity(final Context context, final String phoneNumber, final Point clickPosition)255 public void launchPhoneCallActivity(final Context context, final String phoneNumber, 256 final Point clickPosition) { 257 final Intent intent = new Intent(Intent.ACTION_CALL, 258 Uri.parse(UriUtil.SCHEME_TEL + phoneNumber)); 259 final Bundle extras = new Bundle(); 260 extras.putParcelable(CALL_TARGET_CLICK_KEY, clickPosition); 261 intent.putExtra(CALL_TARGET_CLICK_EXTRA_KEY, extras); 262 startExternalActivity(context, intent); 263 } 264 265 @Override launchClassZeroActivity(final Context context, final ContentValues messageValues)266 public void launchClassZeroActivity(final Context context, final ContentValues messageValues) { 267 final Intent classZeroIntent = new Intent(context, ClassZeroActivity.class) 268 .putExtra(UI_INTENT_EXTRA_MESSAGE_VALUES, messageValues) 269 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 270 context.startActivity(classZeroIntent); 271 } 272 273 @Override launchForwardMessageActivity(final Context context, final MessageData message)274 public void launchForwardMessageActivity(final Context context, final MessageData message) { 275 final Intent forwardMessageIntent = new Intent(context, ForwardMessageActivity.class) 276 .putExtra(UI_INTENT_EXTRA_DRAFT_DATA, message); 277 context.startActivity(forwardMessageIntent); 278 } 279 280 @Override launchVCardDetailActivity(final Context context, final Uri vcardUri)281 public void launchVCardDetailActivity(final Context context, final Uri vcardUri) { 282 final Intent vcardDetailIntent = new Intent(context, VCardDetailActivity.class) 283 .putExtra(UI_INTENT_EXTRA_VCARD_URI, vcardUri); 284 context.startActivity(vcardDetailIntent); 285 } 286 287 @Override launchSaveVCardToContactsActivity(final Context context, final Uri vcardUri)288 public void launchSaveVCardToContactsActivity(final Context context, final Uri vcardUri) { 289 Assert.isTrue(MediaScratchFileProvider.isMediaScratchSpaceUri(vcardUri)); 290 final Intent intent = new Intent(); 291 intent.setAction(Intent.ACTION_VIEW); 292 intent.setDataAndType(vcardUri, ContentType.TEXT_VCARD.toLowerCase()); 293 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 294 startExternalActivity(context, intent); 295 } 296 297 @Override launchAttachmentChooserActivity(final Activity activity, final String conversationId, final int requestCode)298 public void launchAttachmentChooserActivity(final Activity activity, 299 final String conversationId, final int requestCode) { 300 final Intent intent = new Intent(activity, AttachmentChooserActivity.class); 301 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId); 302 activity.startActivityForResult(intent, requestCode); 303 } 304 305 @Override launchFullScreenVideoViewer(final Context context, final Uri videoUri)306 public void launchFullScreenVideoViewer(final Context context, final Uri videoUri) { 307 final Intent intent = new Intent(Intent.ACTION_VIEW); 308 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 309 310 // So we don't see "surrounding" images in Gallery 311 intent.putExtra("SingleItemOnly", true); 312 intent.setDataAndType(videoUri, ContentType.VIDEO_UNSPECIFIED); 313 startExternalActivity(context, intent); 314 } 315 316 @Override launchFullScreenPhotoViewer(final Activity activity, final Uri initialPhoto, final Rect initialPhotoBounds, final Uri photosUri)317 public void launchFullScreenPhotoViewer(final Activity activity, final Uri initialPhoto, 318 final Rect initialPhotoBounds, final Uri photosUri) { 319 final PhotoViewIntentBuilder builder = 320 com.android.ex.photo.Intents.newPhotoViewIntentBuilder( 321 activity, BuglePhotoViewActivity.class); 322 builder.setPhotosUri(photosUri.toString()); 323 builder.setInitialPhotoUri(initialPhoto.toString()); 324 builder.setProjection(ConversationImagePartsView.PhotoViewQuery.PROJECTION); 325 326 // Set the location of the imageView so that the photoviewer can animate from that location 327 // to full screen. 328 builder.setScaleAnimation(initialPhotoBounds.left, initialPhotoBounds.top, 329 initialPhotoBounds.width(), initialPhotoBounds.height()); 330 331 builder.setDisplayThumbsFullScreen(false); 332 builder.setMaxInitialScale(8); 333 activity.startActivity(builder.build()); 334 activity.overridePendingTransition(0, 0); 335 } 336 337 @Override launchApplicationSettingsActivity(final Context context, final boolean topLevel)338 public void launchApplicationSettingsActivity(final Context context, final boolean topLevel) { 339 final Intent intent = new Intent(context, ApplicationSettingsActivity.class); 340 intent.putExtra(UI_INTENT_EXTRA_TOP_LEVEL_SETTINGS, topLevel); 341 context.startActivity(intent); 342 } 343 344 @Override launchPerSubscriptionSettingsActivity(final Context context, final int subId, final String settingTitle)345 public void launchPerSubscriptionSettingsActivity(final Context context, final int subId, 346 final String settingTitle) { 347 final Intent intent = getPerSubscriptionSettingsIntent(context, subId, settingTitle); 348 context.startActivity(intent); 349 } 350 351 @Override getViewUrlIntent(final String url)352 public Intent getViewUrlIntent(final String url) { 353 final Uri uri = Uri.parse(url); 354 return new Intent(Intent.ACTION_VIEW, uri); 355 } 356 357 @Override broadcastConversationSelfIdChange(final Context context, final String conversationId, final String conversationSelfId)358 public void broadcastConversationSelfIdChange(final Context context, 359 final String conversationId, final String conversationSelfId) { 360 final Intent intent = new Intent(CONVERSATION_SELF_ID_CHANGE_BROADCAST_ACTION); 361 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId); 362 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_SELF_ID, conversationSelfId); 363 LocalBroadcastManager.getInstance(context).sendBroadcast(intent); 364 } 365 366 @Override getPendingIntentForConversationListActivity(final Context context)367 public PendingIntent getPendingIntentForConversationListActivity(final Context context) { 368 final Intent intent = getConversationListActivityIntent(context); 369 return getPendingIntentWithParentStack(context, intent, 0); 370 } 371 372 @Override getPendingIntentForConversationActivity(final Context context, final String conversationId, final MessageData draft)373 public PendingIntent getPendingIntentForConversationActivity(final Context context, 374 final String conversationId, final MessageData draft) { 375 final Intent intent = getConversationActivityIntent(context, conversationId, draft, 376 false /* withCustomTransition */); 377 // Ensure that the platform doesn't reuse PendingIntents across conversations 378 intent.setData(MessagingContentProvider.buildConversationMetadataUri(conversationId)); 379 return getPendingIntentWithParentStack(context, intent, 0); 380 } 381 382 @Override getIntentForConversationActivity(final Context context, final String conversationId, final MessageData draft)383 public Intent getIntentForConversationActivity(final Context context, 384 final String conversationId, final MessageData draft) { 385 final Intent intent = getConversationActivityIntent(context, conversationId, draft, 386 false /* withCustomTransition */); 387 return intent; 388 } 389 390 @Override getPendingIntentForSendingMessageToConversation(final Context context, final String conversationId, final String selfId, final boolean requiresMms, final int requestCode)391 public PendingIntent getPendingIntentForSendingMessageToConversation(final Context context, 392 final String conversationId, final String selfId, final boolean requiresMms, 393 final int requestCode) { 394 final Intent intent = new Intent(context, RemoteInputEntrypointActivity.class); 395 intent.setAction(Intent.ACTION_SENDTO); 396 // Ensure that the platform doesn't reuse PendingIntents across conversations 397 intent.setData(MessagingContentProvider.buildConversationMetadataUri(conversationId)); 398 intent.putExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID, conversationId); 399 intent.putExtra(UIIntents.UI_INTENT_EXTRA_SELF_ID, selfId); 400 intent.putExtra(UIIntents.UI_INTENT_EXTRA_REQUIRES_MMS, requiresMms); 401 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 402 return getPendingIntentWithParentStack(context, intent, requestCode); 403 } 404 405 @Override getPendingIntentForClearingNotifications(final Context context, final int updateTargets, final ConversationIdSet conversationIdSet, final int requestCode)406 public PendingIntent getPendingIntentForClearingNotifications(final Context context, 407 final int updateTargets, final ConversationIdSet conversationIdSet, 408 final int requestCode) { 409 final Intent intent = new Intent(context, NotificationReceiver.class); 410 intent.setAction(ACTION_RESET_NOTIFICATIONS); 411 intent.putExtra(UI_INTENT_EXTRA_NOTIFICATIONS_UPDATE, updateTargets); 412 if (conversationIdSet != null) { 413 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID_SET, 414 conversationIdSet.getDelimitedString()); 415 } 416 return PendingIntent.getBroadcast(context, 417 requestCode, intent, 418 PendingIntent.FLAG_UPDATE_CURRENT); 419 } 420 421 /** 422 * Gets a PendingIntent associated with an Intent to start an Activity. All notifications 423 * that starts an Activity must use this method to get a PendingIntent, which achieves two 424 * goals: 425 * 1. The target activities will be created, with any existing ones destroyed. This ensures 426 * we don't end up with multiple instances of ConversationListActivity, for example. 427 * 2. The target activity, when launched, will have its backstack correctly constructed so 428 * back navigation will work correctly. 429 */ getPendingIntentWithParentStack(final Context context, final Intent intent, final int requestCode)430 private static PendingIntent getPendingIntentWithParentStack(final Context context, 431 final Intent intent, final int requestCode) { 432 final TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); 433 // Adds the back stack for the Intent (plus the Intent itself) 434 stackBuilder.addNextIntentWithParentStack(intent); 435 final PendingIntent resultPendingIntent = 436 stackBuilder.getPendingIntent(requestCode, PendingIntent.FLAG_UPDATE_CURRENT); 437 return resultPendingIntent; 438 } 439 440 @Override getRingtonePickerIntent(final String title, final Uri existingUri, final Uri defaultUri, final int toneType)441 public Intent getRingtonePickerIntent(final String title, final Uri existingUri, 442 final Uri defaultUri, final int toneType) { 443 return new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) 444 .putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, toneType) 445 .putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, title) 446 .putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, existingUri) 447 .putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, defaultUri); 448 } 449 450 @Override getPendingIntentForLowStorageNotifications(final Context context)451 public PendingIntent getPendingIntentForLowStorageNotifications(final Context context) { 452 final TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 453 final Intent conversationListIntent = getConversationListActivityIntent(context); 454 taskStackBuilder.addNextIntent(conversationListIntent); 455 taskStackBuilder.addNextIntentWithParentStack( 456 getSmsStorageLowWarningActivityIntent(context)); 457 458 return taskStackBuilder.getPendingIntent( 459 0, PendingIntent.FLAG_UPDATE_CURRENT); 460 } 461 462 @Override getPendingIntentForSecondaryUserNewMessageNotification( final Context context)463 public PendingIntent getPendingIntentForSecondaryUserNewMessageNotification( 464 final Context context) { 465 return getPendingIntentForConversationListActivity(context); 466 } 467 468 @Override getWirelessAlertsIntent()469 public Intent getWirelessAlertsIntent() { 470 final Intent intent = new Intent(Intent.ACTION_MAIN); 471 intent.setComponent(new ComponentName(CMAS_COMPONENT, CELL_BROADCAST_LIST_ACTIVITY)); 472 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 473 return intent; 474 } 475 476 @Override getApnEditorIntent(final Context context, final String rowId, final int subId)477 public Intent getApnEditorIntent(final Context context, final String rowId, final int subId) { 478 final Intent intent = new Intent(context, ApnEditorActivity.class); 479 intent.putExtra(UI_INTENT_EXTRA_APN_ROW_ID, rowId); 480 intent.putExtra(UI_INTENT_EXTRA_SUB_ID, subId); 481 return intent; 482 } 483 484 @Override getApnSettingsIntent(final Context context, final int subId)485 public Intent getApnSettingsIntent(final Context context, final int subId) { 486 final Intent intent = new Intent(context, ApnSettingsActivity.class) 487 .putExtra(UI_INTENT_EXTRA_SUB_ID, subId); 488 return intent; 489 } 490 491 @Override getAdvancedSettingsIntent(final Context context)492 public Intent getAdvancedSettingsIntent(final Context context) { 493 return getPerSubscriptionSettingsIntent(context, ParticipantData.DEFAULT_SELF_SUB_ID, null); 494 } 495 496 @Override getChangeDefaultSmsAppIntent(final Activity activity)497 public Intent getChangeDefaultSmsAppIntent(final Activity activity) { 498 final Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT); 499 intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, activity.getPackageName()); 500 return intent; 501 } 502 503 @Override launchBrowserForUrl(final Context context, final String url)504 public void launchBrowserForUrl(final Context context, final String url) { 505 final Intent intent = getViewUrlIntent(url); 506 startExternalActivity(context, intent); 507 } 508 509 /** 510 * Provides a safe way to handle external activities which may not exist. 511 */ startExternalActivity(final Context context, final Intent intent)512 private void startExternalActivity(final Context context, final Intent intent) { 513 try { 514 context.startActivity(intent); 515 } catch (final ActivityNotFoundException ex) { 516 LogUtil.w(LogUtil.BUGLE_TAG, "Couldn't find activity:", ex); 517 UiUtils.showToastAtBottom(R.string.activity_not_found_message); 518 } 519 } 520 getPerSubscriptionSettingsIntent(final Context context, final int subId, @Nullable final String settingTitle)521 private Intent getPerSubscriptionSettingsIntent(final Context context, final int subId, 522 @Nullable final String settingTitle) { 523 return new Intent(context, PerSubscriptionSettingsActivity.class) 524 .putExtra(UI_INTENT_EXTRA_SUB_ID, subId) 525 .putExtra(UI_INTENT_EXTRA_PER_SUBSCRIPTION_SETTING_TITLE, settingTitle); 526 } 527 528 @Override getLaunchConversationActivityIntent(final Context context)529 public Intent getLaunchConversationActivityIntent(final Context context) { 530 final Intent intent = new Intent(context, LaunchConversationActivity.class); 531 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY); 532 return intent; 533 } 534 535 @Override kickMediaScanner(final Context context, final String volume)536 public void kickMediaScanner(final Context context, final String volume) { 537 final Intent intent = new Intent(MEDIA_SCANNER_SCAN_ACTION) 538 .putExtra(MediaStore.MEDIA_SCANNER_VOLUME, volume) 539 .setClassName(MEDIA_SCANNER_PACKAGE, MEDIA_SCANNER_CLASS); 540 context.startService(intent); 541 } 542 543 @Override getWidgetPendingIntentForConversationActivity(final Context context, final String conversationId, final int requestCode)544 public PendingIntent getWidgetPendingIntentForConversationActivity(final Context context, 545 final String conversationId, final int requestCode) { 546 final Intent intent = getConversationActivityIntent(context, null, null, 547 false /* withCustomTransition */); 548 if (conversationId != null) { 549 intent.putExtra(UI_INTENT_EXTRA_CONVERSATION_ID, conversationId); 550 551 // Set the action to something unique to this conversation so if someone calls this 552 // function again on a different conversation, they'll get a new PendingIntent instead 553 // of the old one. 554 intent.setAction(ACTION_WIDGET_CONVERSATION + conversationId); 555 } 556 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 557 return getPendingIntentWithParentStack(context, intent, requestCode); 558 } 559 560 @Override getWidgetPendingIntentForConversationListActivity( final Context context)561 public PendingIntent getWidgetPendingIntentForConversationListActivity( 562 final Context context) { 563 final Intent intent = getConversationListActivityIntent(context); 564 return getPendingIntentWithParentStack(context, intent, 0); 565 } 566 567 @Override getWidgetPendingIntentForConfigurationActivity(final Context context, final int appWidgetId)568 public PendingIntent getWidgetPendingIntentForConfigurationActivity(final Context context, 569 final int appWidgetId) { 570 final Intent configureIntent = new Intent(context, WidgetPickConversationActivity.class); 571 configureIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 572 configureIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); 573 configureIntent.setData(Uri.parse(configureIntent.toUri(Intent.URI_INTENT_SCHEME))); 574 configureIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY); 575 return getPendingIntentWithParentStack(context, configureIntent, 0); 576 } 577 } 578