PhotoPage.java revision 66ca848b2f58b813d366642088d274a1b7c4a90c
1/* 2 * Copyright (C) 2010 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 17package com.android.gallery3d.app; 18 19import android.app.ActionBar.OnMenuVisibilityListener; 20import android.app.Activity; 21import android.content.ActivityNotFoundException; 22import android.content.ContentResolver; 23import android.content.Context; 24import android.content.Intent; 25import android.graphics.Rect; 26import android.net.Uri; 27import android.nfc.NfcAdapter; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.Message; 31import android.view.Menu; 32import android.view.MenuInflater; 33import android.view.MenuItem; 34import android.view.View; 35import android.view.WindowManager; 36import android.widget.ShareActionProvider; 37import android.widget.Toast; 38 39import com.android.gallery3d.R; 40import com.android.gallery3d.data.DataManager; 41import com.android.gallery3d.data.MediaDetails; 42import com.android.gallery3d.data.MediaItem; 43import com.android.gallery3d.data.MediaObject; 44import com.android.gallery3d.data.MediaSet; 45import com.android.gallery3d.data.MtpDevice; 46import com.android.gallery3d.data.Path; 47import com.android.gallery3d.data.SnailSource; 48import com.android.gallery3d.picasasource.PicasaSource; 49import com.android.gallery3d.ui.DetailsHelper; 50import com.android.gallery3d.ui.DetailsHelper.CloseListener; 51import com.android.gallery3d.ui.DetailsHelper.DetailsSource; 52import com.android.gallery3d.ui.GLCanvas; 53import com.android.gallery3d.ui.GLView; 54import com.android.gallery3d.ui.ImportCompleteListener; 55import com.android.gallery3d.ui.MenuExecutor; 56import com.android.gallery3d.ui.PhotoView; 57import com.android.gallery3d.ui.ScreenNail; 58import com.android.gallery3d.ui.SelectionManager; 59import com.android.gallery3d.ui.SynchronizedHandler; 60import com.android.gallery3d.util.GalleryUtils; 61import com.android.gallery3d.util.MediaSetUtils; 62 63public class PhotoPage extends ActivityState implements 64 PhotoView.Listener, OrientationManager.Listener, AppBridge.Server { 65 private static final String TAG = "PhotoPage"; 66 67 private static final int MSG_HIDE_BARS = 1; 68 private static final int MSG_LOCK_ORIENTATION = 2; 69 private static final int MSG_UNLOCK_ORIENTATION = 3; 70 private static final int MSG_ON_FULL_SCREEN_CHANGED = 4; 71 private static final int MSG_UPDATE_ACTION_BAR = 5; 72 73 private static final int HIDE_BARS_TIMEOUT = 3500; 74 75 private static final int REQUEST_SLIDESHOW = 1; 76 private static final int REQUEST_CROP = 2; 77 private static final int REQUEST_CROP_PICASA = 3; 78 private static final int REQUEST_EDIT = 4; 79 80 public static final String KEY_MEDIA_SET_PATH = "media-set-path"; 81 public static final String KEY_MEDIA_ITEM_PATH = "media-item-path"; 82 public static final String KEY_INDEX_HINT = "index-hint"; 83 public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect"; 84 public static final String KEY_APP_BRIDGE = "app-bridge"; 85 86 public static final String KEY_RETURN_INDEX_HINT = "return-index-hint"; 87 88 private GalleryApp mApplication; 89 private SelectionManager mSelectionManager; 90 91 private PhotoView mPhotoView; 92 private PhotoPage.Model mModel; 93 private DetailsHelper mDetailsHelper; 94 private boolean mShowDetails; 95 private Path mPendingSharePath; 96 97 // mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied. 98 // E.g., viewing a photo in gmail attachment 99 private MediaSet mMediaSet; 100 private Menu mMenu; 101 102 private int mCurrentIndex = 0; 103 private Handler mHandler; 104 private boolean mShowBars = true; 105 // The value of canShowBars() last time the bar updates state. 106 private boolean mCanShowBars = false; 107 private volatile boolean mActionBarAllowed = true; 108 private GalleryActionBar mActionBar; 109 private MyMenuVisibilityListener mMenuVisibilityListener; 110 private boolean mIsMenuVisible; 111 private MediaItem mCurrentPhoto = null; 112 private MenuExecutor mMenuExecutor; 113 private boolean mIsActive; 114 private ShareActionProvider mShareActionProvider; 115 private String mSetPathString; 116 // This is the original mSetPathString before adding the camera preview item. 117 private String mOriginalSetPathString; 118 private AppBridge mAppBridge; 119 private ScreenNail mScreenNail; 120 private MediaItem mScreenNailItem; 121 private OrientationManager mOrientationManager; 122 123 private NfcAdapter mNfcAdapter; 124 125 public static interface Model extends PhotoView.Model { 126 public void resume(); 127 public void pause(); 128 public boolean isEmpty(); 129 public MediaItem getCurrentMediaItem(); 130 public void setCurrentPhoto(Path path, int indexHint); 131 } 132 133 private class MyMenuVisibilityListener implements OnMenuVisibilityListener { 134 @Override 135 public void onMenuVisibilityChanged(boolean isVisible) { 136 mIsMenuVisible = isVisible; 137 refreshHidingMessage(); 138 } 139 } 140 141 private final GLView mRootPane = new GLView() { 142 143 @Override 144 protected void renderBackground(GLCanvas view) { 145 view.clearBuffer(); 146 } 147 148 @Override 149 protected void onLayout( 150 boolean changed, int left, int top, int right, int bottom) { 151 mPhotoView.layout(0, 0, right - left, bottom - top); 152 if (mShowDetails) { 153 mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom); 154 } 155 } 156 157 @Override 158 protected void orient(int displayRotation, int compensation) { 159 displayRotation = mOrientationManager.getDisplayRotation(); 160 Log.d(TAG, "orient -- display rotation " + displayRotation 161 + ", compensation = " + compensation); 162 super.orient(displayRotation, compensation); 163 } 164 }; 165 166 @Override 167 public void onCreate(Bundle data, Bundle restoreState) { 168 mActionBar = mActivity.getGalleryActionBar(); 169 mSelectionManager = new SelectionManager(mActivity, false); 170 mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager); 171 172 mPhotoView = new PhotoView(mActivity); 173 mPhotoView.setListener(this); 174 mRootPane.addComponent(mPhotoView); 175 mApplication = (GalleryApp)((Activity) mActivity).getApplication(); 176 mOrientationManager = mActivity.getOrientationManager(); 177 mOrientationManager.addListener(this); 178 179 mSetPathString = data.getString(KEY_MEDIA_SET_PATH); 180 mOriginalSetPathString = mSetPathString; 181 mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity.getAndroidContext()); 182 Path itemPath = Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)); 183 184 if (mSetPathString != null) { 185 mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE); 186 if (mAppBridge != null) { 187 mOrientationManager.lockOrientation(); 188 189 // Get the ScreenNail from AppBridge and register it. 190 mScreenNail = mAppBridge.attachScreenNail(); 191 int id = SnailSource.registerScreenNail(mScreenNail); 192 Path screenNailSetPath = SnailSource.getSetPath(id); 193 Path screenNailItemPath = SnailSource.getItemPath(id); 194 mScreenNailItem = (MediaItem) mActivity.getDataManager() 195 .getMediaObject(screenNailItemPath); 196 197 // Combine the original MediaSet with the one for CameraScreenNail. 198 mSetPathString = "/combo/item/{" + screenNailSetPath + 199 "," + mSetPathString + "}"; 200 201 // Start from the screen nail. 202 itemPath = screenNailItemPath; 203 204 // Action bar should not be displayed when camera starts. 205 mFlags |= FLAG_HIDE_ACTION_BAR; 206 mShowBars = false; 207 } 208 209 mMediaSet = mActivity.getDataManager().getMediaSet(mSetPathString); 210 mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0); 211 if (mMediaSet == null) { 212 Log.w(TAG, "failed to restore " + mSetPathString); 213 } 214 PhotoDataAdapter pda = new PhotoDataAdapter( 215 mActivity, mPhotoView, mMediaSet, itemPath, mCurrentIndex, 216 mAppBridge == null ? -1 : 0); 217 mModel = pda; 218 mPhotoView.setModel(mModel); 219 220 pda.setDataListener(new PhotoDataAdapter.DataListener() { 221 222 @Override 223 public void onPhotoChanged(int index, Path item) { 224 mCurrentIndex = index; 225 if (item != null) { 226 MediaItem photo = mModel.getCurrentMediaItem(); 227 if (photo != null) updateCurrentPhoto(photo); 228 } 229 updateBars(); 230 } 231 232 @Override 233 public void onLoadingFinished() { 234 GalleryUtils.setSpinnerVisibility((Activity) mActivity, false); 235 if (!mModel.isEmpty()) { 236 MediaItem photo = mModel.getCurrentMediaItem(); 237 if (photo != null) updateCurrentPhoto(photo); 238 } else if (mIsActive) { 239 mActivity.getStateManager().finishState(PhotoPage.this); 240 } 241 } 242 243 @Override 244 public void onLoadingStarted() { 245 GalleryUtils.setSpinnerVisibility((Activity) mActivity, true); 246 } 247 }); 248 } else { 249 // Get default media set by the URI 250 MediaItem mediaItem = (MediaItem) 251 mActivity.getDataManager().getMediaObject(itemPath); 252 mModel = new SinglePhotoDataAdapter(mActivity, mPhotoView, mediaItem); 253 mPhotoView.setModel(mModel); 254 updateCurrentPhoto(mediaItem); 255 } 256 257 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { 258 @Override 259 public void handleMessage(Message message) { 260 switch (message.what) { 261 case MSG_HIDE_BARS: { 262 hideBars(); 263 break; 264 } 265 case MSG_LOCK_ORIENTATION: { 266 mOrientationManager.lockOrientation(); 267 updateBars(); 268 break; 269 } 270 case MSG_UNLOCK_ORIENTATION: { 271 mOrientationManager.unlockOrientation(); 272 updateBars(); 273 break; 274 } 275 case MSG_ON_FULL_SCREEN_CHANGED: { 276 mAppBridge.onFullScreenChanged(message.arg1 == 1); 277 break; 278 } 279 case MSG_UPDATE_ACTION_BAR: { 280 updateBars(); 281 break; 282 } 283 default: throw new AssertionError(message.what); 284 } 285 } 286 }; 287 288 // start the opening animation only if it's not restored. 289 if (restoreState == null) { 290 mPhotoView.setOpenAnimationRect((Rect) data.getParcelable(KEY_OPEN_ANIMATION_RECT)); 291 } 292 } 293 294 private void updateShareURI(Path path) { 295 if (mShareActionProvider != null) { 296 DataManager manager = mActivity.getDataManager(); 297 int type = manager.getMediaType(path); 298 Intent intent = new Intent(Intent.ACTION_SEND); 299 intent.setType(MenuExecutor.getMimeType(type)); 300 intent.putExtra(Intent.EXTRA_STREAM, manager.getContentUri(path)); 301 mShareActionProvider.setShareIntent(intent); 302 if (mNfcAdapter != null) { 303 mNfcAdapter.setBeamPushUris(new Uri[]{manager.getContentUri(path)}, 304 (Activity)mActivity); 305 } 306 mPendingSharePath = null; 307 } else { 308 // This happens when ActionBar is not created yet. 309 mPendingSharePath = path; 310 } 311 } 312 313 private void updateCurrentPhoto(MediaItem photo) { 314 if (mCurrentPhoto == photo) return; 315 mCurrentPhoto = photo; 316 if (mCurrentPhoto == null) return; 317 updateMenuOperations(); 318 updateTitle(); 319 if (mShowDetails) { 320 mDetailsHelper.reloadDetails(mModel.getCurrentIndex()); 321 } 322 mPhotoView.showVideoPlayIcon( 323 photo.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO); 324 325 if ((photo.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) { 326 updateShareURI(photo.getPath()); 327 } 328 } 329 330 private void updateTitle() { 331 if (mCurrentPhoto == null) return; 332 boolean showTitle = mActivity.getAndroidContext().getResources().getBoolean( 333 R.bool.show_action_bar_title); 334 if (showTitle && mCurrentPhoto.getName() != null) 335 mActionBar.setTitle(mCurrentPhoto.getName()); 336 else 337 mActionBar.setTitle(""); 338 } 339 340 private void updateMenuOperations() { 341 if (mMenu == null) return; 342 MenuItem item = mMenu.findItem(R.id.action_slideshow); 343 if (item != null) { 344 item.setVisible(canDoSlideShow()); 345 } 346 if (mCurrentPhoto == null) return; 347 int supportedOperations = mCurrentPhoto.getSupportedOperations(); 348 if (!GalleryUtils.isEditorAvailable((Context) mActivity, "image/*")) { 349 supportedOperations &= ~MediaObject.SUPPORT_EDIT; 350 } 351 352 MenuExecutor.updateMenuOperation(mMenu, supportedOperations); 353 } 354 355 private boolean canDoSlideShow() { 356 if (mMediaSet == null || mCurrentPhoto == null) { 357 return false; 358 } 359 if (mCurrentPhoto.getMediaType() != MediaObject.MEDIA_TYPE_IMAGE) { 360 return false; 361 } 362 if (mMediaSet instanceof MtpDevice) { 363 return false; 364 } 365 return true; 366 } 367 368 ////////////////////////////////////////////////////////////////////////// 369 // Action Bar show/hide management 370 ////////////////////////////////////////////////////////////////////////// 371 372 private void showBars() { 373 if (mShowBars) return; 374 mShowBars = true; 375 mActionBar.show(); 376 WindowManager.LayoutParams params = 377 ((Activity) mActivity).getWindow().getAttributes(); 378 params.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 379 ((Activity) mActivity).getWindow().setAttributes(params); 380 refreshHidingMessage(); 381 } 382 383 private void hideBars() { 384 if (!mShowBars) return; 385 mShowBars = false; 386 mActionBar.hide(); 387 WindowManager.LayoutParams params = 388 ((Activity) mActivity).getWindow().getAttributes(); 389 params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE; 390 ((Activity) mActivity).getWindow().setAttributes(params); 391 mHandler.removeMessages(MSG_HIDE_BARS); 392 } 393 394 private void refreshHidingMessage() { 395 mHandler.removeMessages(MSG_HIDE_BARS); 396 if (!mIsMenuVisible) { 397 mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT); 398 } 399 } 400 401 private boolean canShowBars() { 402 // No bars if we are showing camera preview. 403 if (mAppBridge != null && mCurrentIndex == 0) return false; 404 // No bars if it's not allowed. 405 if (!mActionBarAllowed) return false; 406 // No bars if the orientation is locked. 407 if (mOrientationManager.isOrientationLocked()) return false; 408 409 return true; 410 } 411 412 private void toggleBars() { 413 mCanShowBars = canShowBars(); 414 if (mShowBars) { 415 hideBars(); 416 } else { 417 if (mCanShowBars) showBars(); 418 } 419 } 420 421 private void updateBars() { 422 boolean v = canShowBars(); 423 if (mCanShowBars == v) return; 424 mCanShowBars = v; 425 426 if (mCanShowBars) { 427 showBars(); 428 } else { 429 hideBars(); 430 } 431 } 432 433 @Override 434 public void onOrientationCompensationChanged(int degrees) { 435 mActivity.getGLRoot().setOrientationCompensation(degrees); 436 } 437 438 @Override 439 protected void onBackPressed() { 440 if (mShowDetails) { 441 hideDetails(); 442 } else if (mScreenNail == null 443 || !switchWithCaptureAnimation(-1)) { 444 // We are leaving this page. Set the result now. 445 setResult(); 446 super.onBackPressed(); 447 } 448 } 449 450 private void onUpPressed() { 451 if (mActivity.getStateManager().getStateCount() > 1) { 452 super.onBackPressed(); 453 } 454 455 if (mOriginalSetPathString == null) return; 456 457 if (mAppBridge == null) { 458 // We're in view mode so set up the stacks on our own. 459 Bundle data = new Bundle(getData()); 460 data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); 461 data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, 462 mActivity.getDataManager().getTopSetPath( 463 DataManager.INCLUDE_ALL)); 464 mActivity.getStateManager().switchState(this, AlbumPage.class, data); 465 } else { 466 // Start the real gallery activity to view the camera roll. 467 Uri uri = Uri.parse("content://media/external/file?bucketId=" 468 + MediaSetUtils.CAMERA_BUCKET_ID); 469 Intent intent = new Intent(Intent.ACTION_VIEW); 470 intent.setDataAndType(uri, ContentResolver.CURSOR_DIR_BASE_TYPE + "/image"); 471 ((Activity) mActivity).startActivity(intent); 472 } 473 } 474 475 private void setResult() { 476 Intent result = null; 477 if (!mPhotoView.getFilmMode()) { 478 result = new Intent(); 479 result.putExtra(KEY_RETURN_INDEX_HINT, mCurrentIndex); 480 } 481 setStateResult(Activity.RESULT_OK, result); 482 } 483 484 ////////////////////////////////////////////////////////////////////////// 485 // AppBridge.Server interface 486 ////////////////////////////////////////////////////////////////////////// 487 488 @Override 489 public void setCameraNaturalFrame(Rect frame) { 490 mPhotoView.setCameraNaturalFrame(frame); 491 } 492 493 @Override 494 public boolean switchWithCaptureAnimation(int offset) { 495 return mPhotoView.switchWithCaptureAnimation(offset); 496 } 497 498 @Override 499 protected boolean onCreateActionBar(Menu menu) { 500 MenuInflater inflater = ((Activity) mActivity).getMenuInflater(); 501 inflater.inflate(R.menu.photo, menu); 502 mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu); 503 if (mPendingSharePath != null) updateShareURI(mPendingSharePath); 504 mMenu = menu; 505 updateMenuOperations(); 506 updateTitle(); 507 return true; 508 } 509 510 @Override 511 protected boolean onItemSelected(MenuItem item) { 512 MediaItem current = mModel.getCurrentMediaItem(); 513 514 if (current == null) { 515 // item is not ready, ignore 516 return true; 517 } 518 519 int currentIndex = mModel.getCurrentIndex(); 520 Path path = current.getPath(); 521 522 DataManager manager = mActivity.getDataManager(); 523 int action = item.getItemId(); 524 boolean needsConfirm = false; 525 switch (action) { 526 case android.R.id.home: { 527 onUpPressed(); 528 return true; 529 } 530 case R.id.action_slideshow: { 531 Bundle data = new Bundle(); 532 data.putString(SlideshowPage.KEY_SET_PATH, mMediaSet.getPath().toString()); 533 data.putString(SlideshowPage.KEY_ITEM_PATH, path.toString()); 534 data.putInt(SlideshowPage.KEY_PHOTO_INDEX, currentIndex); 535 data.putBoolean(SlideshowPage.KEY_REPEAT, true); 536 mActivity.getStateManager().startStateForResult( 537 SlideshowPage.class, REQUEST_SLIDESHOW, data); 538 return true; 539 } 540 case R.id.action_crop: { 541 Activity activity = (Activity) mActivity; 542 Intent intent = new Intent(CropImage.CROP_ACTION); 543 intent.setClass(activity, CropImage.class); 544 intent.setData(manager.getContentUri(path)); 545 activity.startActivityForResult(intent, PicasaSource.isPicasaImage(current) 546 ? REQUEST_CROP_PICASA 547 : REQUEST_CROP); 548 return true; 549 } 550 case R.id.action_edit: { 551 Intent intent = new Intent(Intent.ACTION_EDIT) 552 .setData(manager.getContentUri(path)) 553 .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 554 ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null), 555 REQUEST_EDIT); 556 return true; 557 } 558 case R.id.action_details: { 559 if (mShowDetails) { 560 hideDetails(); 561 } else { 562 showDetails(currentIndex); 563 } 564 return true; 565 } 566 case R.id.action_delete: 567 needsConfirm = true; 568 case R.id.action_setas: 569 case R.id.action_rotate_ccw: 570 case R.id.action_rotate_cw: 571 case R.id.action_show_on_map: 572 mSelectionManager.deSelectAll(); 573 mSelectionManager.toggle(path); 574 mMenuExecutor.onMenuClicked(item, needsConfirm, null); 575 return true; 576 case R.id.action_import: 577 mSelectionManager.deSelectAll(); 578 mSelectionManager.toggle(path); 579 mMenuExecutor.onMenuClicked(item, needsConfirm, 580 new ImportCompleteListener(mActivity)); 581 return true; 582 default : 583 return false; 584 } 585 } 586 587 private void hideDetails() { 588 mShowDetails = false; 589 mDetailsHelper.hide(); 590 } 591 592 private void showDetails(int index) { 593 mShowDetails = true; 594 if (mDetailsHelper == null) { 595 mDetailsHelper = new DetailsHelper(mActivity, mRootPane, new MyDetailsSource()); 596 mDetailsHelper.setCloseListener(new CloseListener() { 597 @Override 598 public void onClose() { 599 hideDetails(); 600 } 601 }); 602 } 603 mDetailsHelper.reloadDetails(index); 604 mDetailsHelper.show(); 605 } 606 607 //////////////////////////////////////////////////////////////////////////// 608 // Callbacks from PhotoView 609 //////////////////////////////////////////////////////////////////////////// 610 @Override 611 public void onSingleTapUp(int x, int y) { 612 if (mAppBridge != null) { 613 if (mAppBridge.onSingleTapUp(x, y)) return; 614 } 615 616 MediaItem item = mModel.getCurrentMediaItem(); 617 if (item == null || item == mScreenNailItem) { 618 // item is not ready or it is camera preview, ignore 619 return; 620 } 621 622 boolean playVideo = 623 (item.getSupportedOperations() & MediaItem.SUPPORT_PLAY) != 0; 624 625 if (playVideo) { 626 // determine if the point is at center (1/6) of the photo view. 627 // (The position of the "play" icon is at center (1/6) of the photo) 628 int w = mPhotoView.getWidth(); 629 int h = mPhotoView.getHeight(); 630 playVideo = (Math.abs(x - w / 2) * 12 <= w) 631 && (Math.abs(y - h / 2) * 12 <= h); 632 } 633 634 if (playVideo) { 635 playVideo((Activity) mActivity, item.getPlayUri(), item.getName()); 636 } else { 637 toggleBars(); 638 } 639 } 640 641 @Override 642 public void lockOrientation() { 643 mHandler.sendEmptyMessage(MSG_LOCK_ORIENTATION); 644 } 645 646 @Override 647 public void unlockOrientation() { 648 mHandler.sendEmptyMessage(MSG_UNLOCK_ORIENTATION); 649 } 650 651 @Override 652 public void onActionBarAllowed(boolean allowed) { 653 mActionBarAllowed = allowed; 654 mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR); 655 } 656 657 @Override 658 public void onFullScreenChanged(boolean full) { 659 Message m = mHandler.obtainMessage( 660 MSG_ON_FULL_SCREEN_CHANGED, full ? 1 : 0, 0); 661 m.sendToTarget(); 662 } 663 664 public static void playVideo(Activity activity, Uri uri, String title) { 665 try { 666 Intent intent = new Intent(Intent.ACTION_VIEW) 667 .setDataAndType(uri, "video/*"); 668 intent.putExtra(Intent.EXTRA_TITLE, title); 669 activity.startActivity(intent); 670 } catch (ActivityNotFoundException e) { 671 Toast.makeText(activity, activity.getString(R.string.video_err), 672 Toast.LENGTH_SHORT).show(); 673 } 674 } 675 676 private void setCurrentPhotoByIntent(Intent intent) { 677 if (intent == null) return; 678 Path path = mApplication.getDataManager() 679 .findPathByUri(intent.getData(), intent.getType()); 680 if (path != null) { 681 mModel.setCurrentPhoto(path, mCurrentIndex); 682 } 683 } 684 685 @Override 686 protected void onStateResult(int requestCode, int resultCode, Intent data) { 687 switch (requestCode) { 688 case REQUEST_EDIT: 689 setCurrentPhotoByIntent(data); 690 break; 691 case REQUEST_CROP: 692 if (resultCode == Activity.RESULT_OK) { 693 setCurrentPhotoByIntent(data); 694 } 695 break; 696 case REQUEST_CROP_PICASA: { 697 if (resultCode == Activity.RESULT_OK) { 698 Context context = mActivity.getAndroidContext(); 699 String message = context.getString(R.string.crop_saved, 700 context.getString(R.string.folder_download)); 701 Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); 702 } 703 break; 704 } 705 case REQUEST_SLIDESHOW: { 706 if (data == null) break; 707 String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH); 708 int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); 709 if (path != null) { 710 mModel.setCurrentPhoto(Path.fromString(path), index); 711 } 712 } 713 } 714 } 715 716 @Override 717 public void onPause() { 718 super.onPause(); 719 mIsActive = false; 720 if (mAppBridge != null) mAppBridge.setServer(null); 721 DetailsHelper.pause(); 722 mPhotoView.pause(); 723 mModel.pause(); 724 mHandler.removeMessages(MSG_HIDE_BARS); 725 mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener); 726 727 mMenuExecutor.pause(); 728 } 729 730 @Override 731 protected void onResume() { 732 super.onResume(); 733 mIsActive = true; 734 setContentPane(mRootPane); 735 736 mModel.resume(); 737 mPhotoView.resume(); 738 if (mMenuVisibilityListener == null) { 739 mMenuVisibilityListener = new MyMenuVisibilityListener(); 740 } 741 mActionBar.setDisplayOptions(mSetPathString != null, true); 742 mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener); 743 744 if (mAppBridge != null) { 745 mAppBridge.setServer(this); 746 mPhotoView.resetToFirstPicture(); 747 } 748 } 749 750 @Override 751 protected void onDestroy() { 752 if (mAppBridge != null) { 753 // Unregister the ScreenNail and notify mAppBridge. 754 SnailSource.unregisterScreenNail(mScreenNail); 755 mAppBridge.detachScreenNail(); 756 mAppBridge = null; 757 mScreenNail = null; 758 } 759 mOrientationManager.removeListener(this); 760 761 // Remove all pending messages. 762 mHandler.removeCallbacksAndMessages(null); 763 super.onDestroy(); 764 } 765 766 private class MyDetailsSource implements DetailsSource { 767 private int mIndex; 768 769 @Override 770 public MediaDetails getDetails() { 771 return mModel.getCurrentMediaItem().getDetails(); 772 } 773 774 @Override 775 public int size() { 776 return mMediaSet != null ? mMediaSet.getMediaItemCount() : 1; 777 } 778 779 @Override 780 public int findIndex(int indexHint) { 781 mIndex = indexHint; 782 return indexHint; 783 } 784 785 @Override 786 public int getIndex() { 787 return mIndex; 788 } 789 } 790} 791