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 17 package com.android.messaging.ui.mediapicker; 18 19 import android.app.Activity; 20 import android.app.Fragment; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.Bundle; 24 import android.os.Handler; 25 import androidx.viewpager.widget.PagerAdapter; 26 import androidx.viewpager.widget.ViewPager; 27 import androidx.appcompat.app.ActionBar; 28 import android.view.LayoutInflater; 29 import android.view.Menu; 30 import android.view.MenuInflater; 31 import android.view.MenuItem; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.ImageButton; 35 import android.widget.LinearLayout; 36 37 import com.android.messaging.Factory; 38 import com.android.messaging.R; 39 import com.android.messaging.datamodel.DataModel; 40 import com.android.messaging.datamodel.binding.Binding; 41 import com.android.messaging.datamodel.binding.BindingBase; 42 import com.android.messaging.datamodel.binding.ImmutableBindingRef; 43 import com.android.messaging.datamodel.data.DraftMessageData; 44 import com.android.messaging.datamodel.data.MediaPickerData; 45 import com.android.messaging.datamodel.data.MessagePartData; 46 import com.android.messaging.datamodel.data.PendingAttachmentData; 47 import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider; 48 import com.android.messaging.ui.BugleActionBarActivity; 49 import com.android.messaging.ui.FixedViewPagerAdapter; 50 import com.android.messaging.util.AccessibilityUtil; 51 import com.android.messaging.util.Assert; 52 import com.android.messaging.util.UiUtils; 53 import com.google.common.annotations.VisibleForTesting; 54 55 import java.util.ArrayList; 56 import java.util.Collection; 57 import java.util.List; 58 59 /** 60 * Fragment used to select or capture media to be added to the message 61 */ 62 public class MediaPicker extends Fragment implements DraftMessageSubscriptionDataProvider { 63 /** The listener interface for events from the media picker */ 64 public interface MediaPickerListener { 65 /** Called when the media picker is opened so the host can accommodate the UI */ onOpened()66 void onOpened(); 67 68 /** 69 * Called when the media picker goes into or leaves full screen mode so the host can 70 * accommodate the fullscreen UI 71 */ onFullScreenChanged(boolean fullScreen)72 void onFullScreenChanged(boolean fullScreen); 73 74 /** 75 * Called when the user selects one or more items 76 * @param items The list of items which were selected 77 */ onItemsSelected(Collection<MessagePartData> items, boolean dismissMediaPicker)78 void onItemsSelected(Collection<MessagePartData> items, boolean dismissMediaPicker); 79 80 /** 81 * Called when the user unselects one item. 82 */ onItemUnselected(MessagePartData item)83 void onItemUnselected(MessagePartData item); 84 85 /** 86 * Called when the media picker is closed. Always called immediately after onItemsSelected 87 */ onDismissed()88 void onDismissed(); 89 90 /** 91 * Called when media item selection is confirmed in a multi-select action. 92 */ onConfirmItemSelection()93 void onConfirmItemSelection(); 94 95 /** 96 * Called when a pending attachment is added. 97 * @param pendingItem the pending attachment data being loaded. 98 */ onPendingItemAdded(PendingAttachmentData pendingItem)99 void onPendingItemAdded(PendingAttachmentData pendingItem); 100 101 /** 102 * Called when a new media chooser is selected. 103 */ onChooserSelected(final int chooserIndex)104 void onChooserSelected(final int chooserIndex); 105 } 106 107 /** The tag used when registering and finding this fragment */ 108 public static final String FRAGMENT_TAG = "mediapicker"; 109 110 // Media type constants that the media picker supports 111 public static final int MEDIA_TYPE_DEFAULT = 0x0000; 112 public static final int MEDIA_TYPE_NONE = 0x0000; 113 public static final int MEDIA_TYPE_IMAGE = 0x0001; 114 public static final int MEDIA_TYPE_VIDEO = 0x0002; 115 public static final int MEDIA_TYPE_AUDIO = 0x0004; 116 public static final int MEDIA_TYPE_VCARD = 0x0008; 117 public static final int MEDIA_TYPE_LOCATION = 0x0010; 118 private static final int MEDA_TYPE_INVALID = 0x0020; 119 public static final int MEDIA_TYPE_ALL = 0xFFFF; 120 121 /** The listener to call when events occur */ 122 private MediaPickerListener mListener; 123 124 /** The handler used to dispatch calls to the listener */ 125 private Handler mListenerHandler; 126 127 /** The bit flags of media types supported */ 128 private int mSupportedMediaTypes; 129 130 /** The list of choosers which could be within the media picker */ 131 private final MediaChooser[] mChoosers; 132 133 /** The list of currently enabled choosers */ 134 private final ArrayList<MediaChooser> mEnabledChoosers; 135 136 /** The currently selected chooser */ 137 private MediaChooser mSelectedChooser; 138 139 /** The main panel that controls the custom layout */ 140 private MediaPickerPanel mMediaPickerPanel; 141 142 /** The linear layout that holds the icons to select individual chooser tabs */ 143 private LinearLayout mTabStrip; 144 145 /** The view pager to swap between choosers */ 146 private ViewPager mViewPager; 147 148 /** The current pager adapter for the view pager */ 149 private FixedViewPagerAdapter<MediaChooser> mPagerAdapter; 150 151 /** True if the media picker is visible */ 152 private boolean mOpen; 153 154 /** The theme color to use to make the media picker match the rest of the UI */ 155 private int mThemeColor; 156 157 @VisibleForTesting 158 final Binding<MediaPickerData> mBinding = BindingBase.createBinding(this); 159 160 /** Provides subscription-related data to access per-subscription configurations. */ 161 private DraftMessageSubscriptionDataProvider mSubscriptionDataProvider; 162 163 /** Provides access to DraftMessageData associated with the current conversation */ 164 private ImmutableBindingRef<DraftMessageData> mDraftMessageDataModel; 165 MediaPicker()166 public MediaPicker() { 167 this(Factory.get().getApplicationContext()); 168 } 169 MediaPicker(final Context context)170 public MediaPicker(final Context context) { 171 mBinding.bind(DataModel.get().createMediaPickerData(context)); 172 mEnabledChoosers = new ArrayList<MediaChooser>(); 173 mChoosers = new MediaChooser[] { 174 new CameraMediaChooser(this), 175 new GalleryMediaChooser(this), 176 new AudioMediaChooser(this), 177 new ContactMediaChooser(this), 178 }; 179 180 mOpen = false; 181 setSupportedMediaTypes(MEDIA_TYPE_ALL); 182 } 183 184 private boolean mIsAttached; 185 private int mStartingMediaTypeOnAttach = MEDA_TYPE_INVALID; 186 private boolean mAnimateOnAttach; 187 188 @Override onAttach(final Activity activity)189 public void onAttach (final Activity activity) { 190 super.onAttach(activity); 191 mIsAttached = true; 192 if (mStartingMediaTypeOnAttach != MEDA_TYPE_INVALID) { 193 // open() was previously called. Do the pending open now. 194 doOpen(mStartingMediaTypeOnAttach, mAnimateOnAttach); 195 } 196 } 197 198 @Override onCreate(final Bundle savedInstanceState)199 public void onCreate(final Bundle savedInstanceState) { 200 super.onCreate(savedInstanceState); 201 mBinding.getData().init(getLoaderManager()); 202 } 203 204 @Override onCreateView( final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)205 public View onCreateView( 206 final LayoutInflater inflater, 207 final ViewGroup container, 208 final Bundle savedInstanceState) { 209 mMediaPickerPanel = (MediaPickerPanel) inflater.inflate( 210 R.layout.mediapicker_fragment, 211 container, 212 false); 213 mMediaPickerPanel.setMediaPicker(this); 214 mTabStrip = (LinearLayout) mMediaPickerPanel.findViewById(R.id.mediapicker_tabstrip); 215 mTabStrip.setBackgroundColor(mThemeColor); 216 for (final MediaChooser chooser : mChoosers) { 217 chooser.onCreateTabButton(inflater, mTabStrip); 218 final boolean enabled = (chooser.getSupportedMediaTypes() & mSupportedMediaTypes) != 219 MEDIA_TYPE_NONE; 220 final ImageButton tabButton = chooser.getTabButton(); 221 if (tabButton != null) { 222 tabButton.setVisibility(enabled ? View.VISIBLE : View.GONE); 223 mTabStrip.addView(tabButton); 224 } 225 } 226 227 mViewPager = (ViewPager) mMediaPickerPanel.findViewById(R.id.mediapicker_view_pager); 228 mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 229 @Override 230 public void onPageScrolled( 231 final int position, 232 final float positionOffset, 233 final int positionOffsetPixels) { 234 } 235 236 @Override 237 public void onPageSelected(int position) { 238 // The position returned is relative to if we are in RtL mode. This class never 239 // switches the indices of the elements if we are in RtL mode so we need to 240 // translate the index back. For example, if the user clicked the item most to the 241 // right in RtL mode we would want the index to appear as 0 here, however the 242 // position returned would the last possible index. 243 if (UiUtils.isRtlMode()) { 244 position = mEnabledChoosers.size() - 1 - position; 245 } 246 selectChooser(mEnabledChoosers.get(position)); 247 } 248 249 @Override 250 public void onPageScrollStateChanged(final int state) { 251 } 252 }); 253 // Camera initialization is expensive, so don't realize offscreen pages if not needed. 254 mViewPager.setOffscreenPageLimit(0); 255 mViewPager.setAdapter(mPagerAdapter); 256 final boolean isTouchExplorationEnabled = AccessibilityUtil.isTouchExplorationEnabled( 257 getActivity()); 258 mMediaPickerPanel.setFullScreenOnly(isTouchExplorationEnabled); 259 mMediaPickerPanel.setExpanded(mOpen, true, mEnabledChoosers.indexOf(mSelectedChooser)); 260 return mMediaPickerPanel; 261 } 262 263 @Override onPause()264 public void onPause() { 265 super.onPause(); 266 CameraManager.get().onPause(); 267 for (final MediaChooser chooser : mEnabledChoosers) { 268 chooser.onPause(); 269 } 270 } 271 272 @Override onResume()273 public void onResume() { 274 super.onResume(); 275 CameraManager.get().onResume(); 276 277 for (final MediaChooser chooser : mEnabledChoosers) { 278 chooser.onResume(); 279 } 280 } 281 282 @Override onActivityResult(final int requestCode, final int resultCode, final Intent data)283 public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { 284 super.onActivityResult(requestCode, resultCode, data); 285 mSelectedChooser.onActivityResult(requestCode, resultCode, data); 286 } 287 288 @Override onDestroy()289 public void onDestroy() { 290 super.onDestroy(); 291 mBinding.unbind(); 292 } 293 294 /** 295 * Sets the theme color to make the media picker match the surrounding UI 296 * @param themeColor The new theme color 297 */ setConversationThemeColor(final int themeColor)298 public void setConversationThemeColor(final int themeColor) { 299 mThemeColor = themeColor; 300 if (mTabStrip != null) { 301 mTabStrip.setBackgroundColor(mThemeColor); 302 } 303 304 for (final MediaChooser chooser : mEnabledChoosers) { 305 chooser.setThemeColor(mThemeColor); 306 } 307 } 308 309 /** 310 * Gets the current conversation theme color. 311 */ getConversationThemeColor()312 public int getConversationThemeColor() { 313 return mThemeColor; 314 } 315 setDraftMessageDataModel(final BindingBase<DraftMessageData> draftBinding)316 public void setDraftMessageDataModel(final BindingBase<DraftMessageData> draftBinding) { 317 mDraftMessageDataModel = Binding.createBindingReference(draftBinding); 318 } 319 getDraftMessageDataModel()320 public ImmutableBindingRef<DraftMessageData> getDraftMessageDataModel() { 321 return mDraftMessageDataModel; 322 } 323 setSubscriptionDataProvider(final DraftMessageSubscriptionDataProvider provider)324 public void setSubscriptionDataProvider(final DraftMessageSubscriptionDataProvider provider) { 325 mSubscriptionDataProvider = provider; 326 } 327 328 @Override getConversationSelfSubId()329 public int getConversationSelfSubId() { 330 return mSubscriptionDataProvider.getConversationSelfSubId(); 331 } 332 333 /** 334 * Opens the media picker and optionally shows the chooser for the supplied media type 335 * @param startingMediaType The media type of the chooser to open if {@link #MEDIA_TYPE_DEFAULT} 336 * is used, then the default chooser from saved shared prefs is opened 337 */ open(final int startingMediaType, final boolean animate)338 public void open(final int startingMediaType, final boolean animate) { 339 mOpen = true; 340 if (mIsAttached) { 341 doOpen(startingMediaType, animate); 342 } else { 343 // open() can get called immediately after the MediaPicker is created. In that case, 344 // we defer doing work as it may require an attached fragment (eg. calling 345 // Fragment#requestPermission) 346 mStartingMediaTypeOnAttach = startingMediaType; 347 mAnimateOnAttach = animate; 348 } 349 } 350 doOpen(int startingMediaType, final boolean animate)351 private void doOpen(int startingMediaType, final boolean animate) { 352 final boolean isTouchExplorationEnabled = AccessibilityUtil.isTouchExplorationEnabled( 353 // getActivity() will be null at this point 354 Factory.get().getApplicationContext()); 355 356 // If no specific starting type is specified (i.e. MEDIA_TYPE_DEFAULT), try to get the 357 // last opened chooser index from shared prefs. 358 if (startingMediaType == MEDIA_TYPE_DEFAULT) { 359 final int selectedChooserIndex = mBinding.getData().getSelectedChooserIndex(); 360 if (selectedChooserIndex >= 0 && selectedChooserIndex < mEnabledChoosers.size()) { 361 selectChooser(mEnabledChoosers.get(selectedChooserIndex)); 362 } else { 363 // This is the first time the picker is being used 364 if (isTouchExplorationEnabled) { 365 // Accessibility defaults to audio attachment mode. 366 startingMediaType = MEDIA_TYPE_AUDIO; 367 } 368 } 369 } 370 371 if (mSelectedChooser == null) { 372 for (final MediaChooser chooser : mEnabledChoosers) { 373 if (startingMediaType == MEDIA_TYPE_DEFAULT || 374 (startingMediaType & chooser.getSupportedMediaTypes()) != MEDIA_TYPE_NONE) { 375 selectChooser(chooser); 376 break; 377 } 378 } 379 } 380 381 if (mSelectedChooser == null) { 382 // Fall back to the first chooser. 383 selectChooser(mEnabledChoosers.get(0)); 384 } 385 386 if (mMediaPickerPanel != null) { 387 mMediaPickerPanel.setFullScreenOnly(isTouchExplorationEnabled); 388 mMediaPickerPanel.setExpanded(true, animate, 389 mEnabledChoosers.indexOf(mSelectedChooser)); 390 } 391 } 392 393 /** @return True if the media picker is open */ isOpen()394 public boolean isOpen() { 395 return mOpen; 396 } 397 398 /** 399 * Sets the list of media types to allow the user to select 400 * @param mediaTypes The bit flags of media types to allow. Can be any combination of the 401 * MEDIA_TYPE_* values 402 */ setSupportedMediaTypes(final int mediaTypes)403 void setSupportedMediaTypes(final int mediaTypes) { 404 mSupportedMediaTypes = mediaTypes; 405 mEnabledChoosers.clear(); 406 boolean selectNextChooser = false; 407 for (final MediaChooser chooser : mChoosers) { 408 final boolean enabled = (chooser.getSupportedMediaTypes() & mSupportedMediaTypes) != 409 MEDIA_TYPE_NONE; 410 if (enabled) { 411 // TODO Add a way to inform the chooser which media types are supported 412 mEnabledChoosers.add(chooser); 413 if (selectNextChooser) { 414 selectChooser(chooser); 415 selectNextChooser = false; 416 } 417 } else if (mSelectedChooser == chooser) { 418 selectNextChooser = true; 419 } 420 final ImageButton tabButton = chooser.getTabButton(); 421 if (tabButton != null) { 422 tabButton.setVisibility(enabled ? View.VISIBLE : View.GONE); 423 } 424 } 425 426 if (selectNextChooser && mEnabledChoosers.size() > 0) { 427 selectChooser(mEnabledChoosers.get(0)); 428 } 429 final MediaChooser[] enabledChoosers = new MediaChooser[mEnabledChoosers.size()]; 430 mEnabledChoosers.toArray(enabledChoosers); 431 mPagerAdapter = new FixedViewPagerAdapter<MediaChooser>(enabledChoosers); 432 if (mViewPager != null) { 433 mViewPager.setAdapter(mPagerAdapter); 434 } 435 436 // Only rebind data if we are currently bound. Otherwise, we must have not 437 // bound to any data yet and should wait until onCreate() to bind data. 438 if (mBinding.isBound() && getActivity() != null) { 439 mBinding.unbind(); 440 mBinding.bind(DataModel.get().createMediaPickerData(getActivity())); 441 mBinding.getData().init(getLoaderManager()); 442 } 443 } 444 getViewPager()445 ViewPager getViewPager() { 446 return mViewPager; 447 } 448 449 /** Hides the media picker, and frees up any resources it’s using */ dismiss(final boolean animate)450 public void dismiss(final boolean animate) { 451 mOpen = false; 452 if (mMediaPickerPanel != null) { 453 mMediaPickerPanel.setExpanded(false, animate, MediaPickerPanel.PAGE_NOT_SET); 454 } 455 mSelectedChooser = null; 456 } 457 458 /** 459 * Sets the listener for the media picker events 460 * @param listener The listener which will receive events 461 */ setListener(final MediaPickerListener listener)462 public void setListener(final MediaPickerListener listener) { 463 Assert.isMainThread(); 464 mListener = listener; 465 mListenerHandler = listener != null ? new Handler() : null; 466 } 467 468 /** @return True if the media picker is in full-screen mode */ isFullScreen()469 public boolean isFullScreen() { 470 return mMediaPickerPanel != null && mMediaPickerPanel.isFullScreen(); 471 } 472 setFullScreen(final boolean fullScreen)473 public void setFullScreen(final boolean fullScreen) { 474 mMediaPickerPanel.setFullScreenView(fullScreen, true); 475 } 476 updateActionBar(final ActionBar actionBar)477 public void updateActionBar(final ActionBar actionBar) { 478 if (getActivity() == null) { 479 return; 480 } 481 if (isFullScreen() && mSelectedChooser != null) { 482 mSelectedChooser.updateActionBar(actionBar); 483 } else { 484 actionBar.hide(); 485 } 486 } 487 488 /** 489 * Selects a new chooser 490 * @param newSelectedChooser The newly selected chooser 491 */ selectChooser(final MediaChooser newSelectedChooser)492 void selectChooser(final MediaChooser newSelectedChooser) { 493 if (mSelectedChooser == newSelectedChooser) { 494 return; 495 } 496 497 if (mSelectedChooser != null) { 498 mSelectedChooser.setSelected(false); 499 } 500 mSelectedChooser = newSelectedChooser; 501 if (mSelectedChooser != null) { 502 mSelectedChooser.setSelected(true); 503 } 504 505 final int chooserIndex = mEnabledChoosers.indexOf(mSelectedChooser); 506 if (mViewPager != null) { 507 mViewPager.setCurrentItem(chooserIndex, true /* smoothScroll */); 508 } 509 510 if (isFullScreen()) { 511 invalidateOptionsMenu(); 512 } 513 514 // Save the newly selected chooser's index so we may directly switch to it the 515 // next time user opens the media picker. 516 mBinding.getData().saveSelectedChooserIndex(chooserIndex); 517 if (mMediaPickerPanel != null) { 518 mMediaPickerPanel.onChooserChanged(); 519 } 520 dispatchChooserSelected(chooserIndex); 521 } 522 canShowIme()523 public boolean canShowIme() { 524 if (mSelectedChooser != null) { 525 return mSelectedChooser.canShowIme(); 526 } 527 return false; 528 } 529 onBackPressed()530 public boolean onBackPressed() { 531 return mSelectedChooser != null && mSelectedChooser.onBackPressed(); 532 } 533 invalidateOptionsMenu()534 void invalidateOptionsMenu() { 535 ((BugleActionBarActivity) getActivity()).supportInvalidateOptionsMenu(); 536 } 537 dispatchOpened()538 void dispatchOpened() { 539 setHasOptionsMenu(false); 540 mOpen = true; 541 mPagerAdapter.notifyDataSetChanged(); 542 if (mListener != null) { 543 mListenerHandler.post(new Runnable() { 544 @Override 545 public void run() { 546 mListener.onOpened(); 547 } 548 }); 549 } 550 if (mSelectedChooser != null) { 551 mSelectedChooser.onFullScreenChanged(false); 552 mSelectedChooser.onOpenedChanged(true); 553 } 554 } 555 dispatchDismissed()556 void dispatchDismissed() { 557 setHasOptionsMenu(false); 558 mOpen = false; 559 if (mListener != null) { 560 mListenerHandler.post(new Runnable() { 561 @Override 562 public void run() { 563 mListener.onDismissed(); 564 } 565 }); 566 } 567 if (mSelectedChooser != null) { 568 mSelectedChooser.onOpenedChanged(false); 569 } 570 } 571 dispatchFullScreen(final boolean fullScreen)572 void dispatchFullScreen(final boolean fullScreen) { 573 setHasOptionsMenu(fullScreen); 574 if (mListener != null) { 575 mListenerHandler.post(new Runnable() { 576 @Override 577 public void run() { 578 mListener.onFullScreenChanged(fullScreen); 579 } 580 }); 581 } 582 if (mSelectedChooser != null) { 583 mSelectedChooser.onFullScreenChanged(fullScreen); 584 } 585 } 586 dispatchItemsSelected(final MessagePartData item, final boolean dismissMediaPicker)587 void dispatchItemsSelected(final MessagePartData item, final boolean dismissMediaPicker) { 588 final List<MessagePartData> items = new ArrayList<MessagePartData>(1); 589 items.add(item); 590 dispatchItemsSelected(items, dismissMediaPicker); 591 } 592 dispatchItemsSelected(final Collection<MessagePartData> items, final boolean dismissMediaPicker)593 void dispatchItemsSelected(final Collection<MessagePartData> items, 594 final boolean dismissMediaPicker) { 595 if (mListener != null) { 596 mListenerHandler.post(new Runnable() { 597 @Override 598 public void run() { 599 mListener.onItemsSelected(items, dismissMediaPicker); 600 } 601 }); 602 } 603 604 if (isFullScreen() && !dismissMediaPicker) { 605 invalidateOptionsMenu(); 606 } 607 } 608 dispatchItemUnselected(final MessagePartData item)609 void dispatchItemUnselected(final MessagePartData item) { 610 if (mListener != null) { 611 mListenerHandler.post(new Runnable() { 612 @Override 613 public void run() { 614 mListener.onItemUnselected(item); 615 } 616 }); 617 } 618 619 if (isFullScreen()) { 620 invalidateOptionsMenu(); 621 } 622 } 623 dispatchConfirmItemSelection()624 void dispatchConfirmItemSelection() { 625 if (mListener != null) { 626 mListenerHandler.post(new Runnable() { 627 @Override 628 public void run() { 629 mListener.onConfirmItemSelection(); 630 } 631 }); 632 } 633 } 634 dispatchPendingItemAdded(final PendingAttachmentData pendingItem)635 void dispatchPendingItemAdded(final PendingAttachmentData pendingItem) { 636 if (mListener != null) { 637 mListenerHandler.post(new Runnable() { 638 @Override 639 public void run() { 640 mListener.onPendingItemAdded(pendingItem); 641 } 642 }); 643 } 644 645 if (isFullScreen()) { 646 invalidateOptionsMenu(); 647 } 648 } 649 dispatchChooserSelected(final int chooserIndex)650 void dispatchChooserSelected(final int chooserIndex) { 651 if (mListener != null) { 652 mListenerHandler.post(new Runnable() { 653 @Override 654 public void run() { 655 mListener.onChooserSelected(chooserIndex); 656 } 657 }); 658 } 659 } 660 canSwipeDownChooser()661 public boolean canSwipeDownChooser() { 662 return mSelectedChooser == null ? false : mSelectedChooser.canSwipeDown(); 663 } 664 isChooserHandlingTouch()665 public boolean isChooserHandlingTouch() { 666 return mSelectedChooser == null ? false : mSelectedChooser.isHandlingTouch(); 667 } 668 stopChooserTouchHandling()669 public void stopChooserTouchHandling() { 670 if (mSelectedChooser != null) { 671 mSelectedChooser.stopTouchHandling(); 672 } 673 } 674 getChooserShowsActionBarInFullScreen()675 boolean getChooserShowsActionBarInFullScreen() { 676 return mSelectedChooser == null ? false : mSelectedChooser.getActionBarTitleResId() != 0; 677 } 678 679 @Override onCreateOptionsMenu(final Menu menu, final MenuInflater inflater)680 public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { 681 if (mSelectedChooser != null) { 682 mSelectedChooser.onCreateOptionsMenu(inflater, menu); 683 } 684 } 685 686 @Override onOptionsItemSelected(final MenuItem item)687 public boolean onOptionsItemSelected(final MenuItem item) { 688 return (mSelectedChooser != null && mSelectedChooser.onOptionsItemSelected(item)) || 689 super.onOptionsItemSelected(item); 690 } 691 getPagerAdapter()692 PagerAdapter getPagerAdapter() { 693 return mPagerAdapter; 694 } 695 resetViewHolderState()696 public void resetViewHolderState() { 697 mPagerAdapter.resetState(); 698 } 699 getMediaPickerDataBinding()700 public ImmutableBindingRef<MediaPickerData> getMediaPickerDataBinding() { 701 return BindingBase.createBindingReference(mBinding); 702 } 703 704 protected static final int CAMERA_PERMISSION_REQUEST_CODE = 1; 705 protected static final int LOCATION_PERMISSION_REQUEST_CODE = 2; 706 protected static final int RECORD_AUDIO_PERMISSION_REQUEST_CODE = 3; 707 protected static final int GALLERY_PERMISSION_REQUEST_CODE = 4; 708 protected static final int READ_CONTACT_PERMISSION_REQUEST_CODE = 5; 709 710 @Override onRequestPermissionsResult( final int requestCode, final String permissions[], final int[] grantResults)711 public void onRequestPermissionsResult( 712 final int requestCode, final String permissions[], final int[] grantResults) { 713 if (mSelectedChooser != null) { 714 mSelectedChooser.onRequestPermissionsResult(requestCode, permissions, grantResults); 715 } 716 } 717 } 718