/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera;
import android.animation.Animator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.drawable.ColorDrawable;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateBeamUrisCallback;
import android.nfc.NfcEvent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.ShareActionProvider;
import android.media.AudioManager;
import android.media.ThumbnailUtils;
import android.telephony.TelephonyManager;
import android.graphics.Bitmap;
import com.android.camera.app.AppManagerFactory;
import com.android.camera.app.PlaceholderManager;
import com.android.camera.app.PanoramaStitchingManager;
import com.android.camera.crop.CropActivity;
import com.android.camera.data.CameraDataAdapter;
import com.android.camera.data.CameraPreviewData;
import com.android.camera.data.FixedFirstDataAdapter;
import com.android.camera.data.FixedLastDataAdapter;
import com.android.camera.data.InProgressDataWrapper;
import com.android.camera.data.LocalData;
import com.android.camera.data.LocalDataAdapter;
import com.android.camera.data.LocalMediaObserver;
import com.android.camera.data.MediaDetails;
import com.android.camera.data.SimpleViewData;
import com.android.camera.tinyplanet.TinyPlanetFragment;
import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.ui.DetailsDialog;
import com.android.camera.ui.FilmStripView;
import com.android.camera.ui.ScrollFilmStripView;
import com.android.camera.util.ApiHelper;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.GcamHelper;
import com.android.camera.util.IntentHelper;
import com.android.camera.util.PhotoSphereHelper;
import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
import com.android.camera.util.UsageStatistics;
import com.android.camera2.R;
import java.io.File;
import android.app.AlertDialog;
import android.content.DialogInterface;
import static com.android.camera.CameraManager.CameraOpenErrorCallback;
@SuppressLint("NewApi")
public class CameraActivity extends Activity implements
ModuleSwitcher.ModuleSwitchListener,
ModuleSwitcherView.ModuleSwitchViewListener,
ActionBar.OnMenuVisibilityListener, StorageUtil.UpdataPathListener,
ShareActionProvider.OnShareTargetSelectedListener {
private static final boolean DEBUG = true;
private static final String TAG = "CAM_Activity";
private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = "android.media.action.STILL_IMAGE_CAMERA_SECURE";
public static final String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
public static final String ACTION_TRIM_VIDEO = "com.android.camera.action.TRIM";
public static final String MEDIA_ITEM_PATH = "media-item-path";
public static final String MEDIA_CAMERA_BUTTON_START = "is-camera-button-start";
// The intent extra for camera from secure lock screen. True if the gallery
// should only show newly captured pictures. sSecureAlbumId does not
// increment. This is used when switching between camera, camcorder, and
// panorama. If the extra is not set, it is in the normal camera mode.
public static final String SECURE_CAMERA_EXTRA = "secure_camera";
/**
* Request code from an activity we started that indicated that we do not
* want to reset the view to the preview in onResume.
*/
public static final int REQ_CODE_DONT_SWITCH_TO_PREVIEW = 142;
public static final int REQ_CODE_GCAM_DEBUG_POSTCAPTURE = 999;
private static final int HIDE_ACTION_BAR = 1;
private static final int UPDATE_THUMBAIL = 2;
private static final int UPDATE_DATEADAPTER = 3;
private static final long SHOW_ACTION_BAR_TIMEOUT_MS = 3000;
private Bitmap bitmap;
/** Whether onResume should reset the view to the preview. */
private boolean mResetToPreviewOnResume = true;
// Supported operations at FilmStripView. Different data has different
// set of supported operations.
private static final int SUPPORT_DELETE = 1 << 0;
private static final int SUPPORT_ROTATE = 1 << 1;
private static final int SUPPORT_INFO = 1 << 2;
private static final int SUPPORT_CROP = 1 << 3;
private static final int SUPPORT_SETAS = 1 << 4;
private static final int SUPPORT_EDIT = 1 << 5;
private static final int SUPPORT_TRIM = 1 << 6;
private static final int SUPPORT_SHARE = 1 << 7;
private static final int SUPPORT_SHARE_PANORAMA360 = 1 << 8;
private static final int SUPPORT_SHOW_ON_MAP = 1 << 9;
private static final int SUPPORT_ALL = 0xffffffff;
private final static int SAMPLE_FACTOR = 8;
/** This data adapter is used by FilmStripView. */
private LocalDataAdapter mDataAdapter;
/** This data adapter represents the real local camera data. */
private LocalDataAdapter mWrappedDataAdapter;
private PanoramaStitchingManager mPanoramaManager;
private PlaceholderManager mPlaceholderManager;
private int mCurrentModuleIndex;
private CameraModule mCurrentModule;
private FrameLayout mAboveFilmstripControlLayout;
private View mCameraModuleRootView;
private ScrollFilmStripView mFilmStripView;
private ProgressBar mBottomProgress;
private View mPanoStitchingPanel;
private int mResultCodeForTesting;
private Intent mResultDataForTesting;
private OnScreenHint mStorageHint;
private long mStorageSpaceBytes = Storage.LOW_STORAGE_THRESHOLD_BYTES;
private boolean mAutoRotateScreen;
private boolean mSecureCamera;
// This is a hack to speed up the start of SecureCamera.
private static boolean sFirstStartAfterScreenOn = true;
private int mLastRawOrientation;
private MyOrientationEventListener mOrientationListener;
private Handler mMainHandler;
private PanoramaViewHelper mPanoramaViewHelper;
private CameraPreviewData mCameraPreviewData;
private ActionBar mActionBar;
private OnActionBarVisibilityListener mOnActionBarVisibilityListener = null;
private Menu mActionBarMenu;
private ViewGroup mUndoDeletionBar;
private boolean mIsUndoingDeletion = false;
private Uri[] mNfcPushUris = new Uri[1];
private ShareActionProvider mStandardShareActionProvider;
private Intent mStandardShareIntent;
private ShareActionProvider mPanoramaShareActionProvider;
private Intent mPanoramaShareIntent;
private LocalMediaObserver mLocalImagesObserver;
private LocalMediaObserver mLocalVideosObserver;
private final int DEFAULT_SYSTEM_UI_VISIBILITY = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
private boolean mPendingDeletion = false;
private Intent mVideoShareIntent;
private Intent mImageShareIntent;
// SPRD: trim video is enable or not
private boolean mTrimvideoEnable = System.getProperty(
"ro.config.trimvideo", "disable") == "enable";
private boolean bCameraButtonStart;
private static final String LAST_IMAGE_PATH = "last_image";
private static final String LAST_VIDEO_PATH = "last_video";
private class MyOrientationEventListener extends OrientationEventListener {
public MyOrientationEventListener(Context context) {
super(context);
}
@Override
public void onOrientationChanged(int orientation) {
// We keep the last known orientation. So if the user first orient
// the camera then point the camera to floor or sky, we still have
// the correct orientation.
if (orientation == ORIENTATION_UNKNOWN) {
return;
}
mLastRawOrientation = orientation;
mCurrentModule.onOrientationChanged(orientation);
}
}
private MediaSaveService mMediaSaveService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder b) {
mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService();
mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
}
@Override
public void onServiceDisconnected(ComponentName className) {
if (mMediaSaveService != null) {
mMediaSaveService.setListener(null);
mMediaSaveService = null;
}
}
};
private CameraOpenErrorCallback mCameraOpenErrorCallback = new CameraOpenErrorCallback() {
@Override
public void onCameraDisabled(int cameraId) {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_OPEN_FAIL, "security");
CameraUtil.showErrorAndFinish(CameraActivity.this,
R.string.camera_disabled);
}
@Override
public void onDeviceOpenFailure(int cameraId) {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_OPEN_FAIL, "open");
CameraUtil.showErrorAndFinish(CameraActivity.this,
R.string.cannot_connect_camera);
}
@Override
public void onReconnectionFailure(CameraManager mgr) {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_OPEN_FAIL, "reconnect");
CameraUtil.showErrorAndFinish(CameraActivity.this,
R.string.cannot_connect_camera);
}
};
// close activity when screen turns off
private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
private BroadcastReceiver mShutDownReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG,
"onReceive ShutDownBroadcastReceiver onReceive isRecording()="
+ isRecording());
if (isRecording()) {
mCurrentModule.onStopClicked();
}
}
};
// @{ SPRD: update dataAdapter for Media change begin
private ContentObserver mMediaChangeObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.d(TAG, "onchange uri = " + uri);
updateDataAdapter(true);
super.onChange(selfChange, uri);
}
}; // SPRD: update dataAdapter for Media change begin end @}
// @{ SPRD: use handler update DataAdapter begin
private boolean notifyUpdate;
public void updateDataAdapter(boolean delay) {
Log.d(TAG, "updateDataAdapter delay = " + delay + " && notifyUpdate = "
+ notifyUpdate);
if (notifyUpdate) {
notifyUpdate = false;
return;
}
if (mMainHandler.hasMessages(UPDATE_DATEADAPTER)) {
mMainHandler.removeMessages(UPDATE_DATEADAPTER);
mMainHandler.sendEmptyMessageDelayed(UPDATE_DATEADAPTER,
delay ? 1000 : 0);
} else {
mMainHandler.sendEmptyMessageDelayed(UPDATE_DATEADAPTER,
delay ? 1000 : 0);
}
} // SPRD: use handler update DataAdapter end @}
// @{ SPRD: stop handler handle updat DataAdapter message begin
public void stopUpdateDataAdapter() {
notifyUpdate = true;
Log.d(TAG, "stopUpdateDataAdapter");
if (mMainHandler.hasMessages(UPDATE_DATEADAPTER))
mMainHandler.removeMessages(UPDATE_DATEADAPTER);
} // SPRD: stop handler handle updat DataAdapter message end @}
// @{ SPRD: receive storage intent broadcast begin
private BroadcastReceiver mStorageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "Received intent action = " + action);
if (action.equals("android.intent.action.MEDIA_MOUNTED")
|| action.equals("android.intent.action.MEDIA_UNMOUNTED")
|| action.equals("android.intent.action.MEDIA_SHARED")) {
updateStorageSpaceAndHint();
UpdatPath();
}
}
};
// SPRD: receive storage intent broadcast end @}
private static BroadcastReceiver sScreenOffReceiver;
private static class ScreenOffReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
sFirstStartAfterScreenOn = true;
}
}
private class MainHandler extends Handler {
public MainHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == HIDE_ACTION_BAR) {
removeMessages(HIDE_ACTION_BAR);
CameraActivity.this.setSystemBarsVisibility(false);
}
if (msg.what == UPDATE_THUMBAIL) {
removeMessages(UPDATE_THUMBAIL);
new LoadThumbnailTask().execute();
}
if (msg.what == UPDATE_DATEADAPTER) {
removeMessages(UPDATE_DATEADAPTER);
if (!mSecureCamera) {
mDataAdapter.requestLoad(getContentResolver());
} else {
mDataAdapter.requestSecureImageLoad();
}
}
}
}
public interface OnActionBarVisibilityListener {
public void onActionBarVisibilityChanged(boolean isVisible);
}
public void setOnActionBarVisibilityListener(
OnActionBarVisibilityListener listener) {
mOnActionBarVisibilityListener = listener;
}
public static boolean isFirstStartAfterScreenOn() {
return sFirstStartAfterScreenOn;
}
public static void resetFirstStartAfterScreenOn() {
sFirstStartAfterScreenOn = false;
}
private String fileNameFromDataID(int dataID) {
final LocalData localData = mDataAdapter.getLocalData(dataID);
File localFile = new File(localData.getPath());
return localFile.getName();
}
private FilmStripView.Listener mFilmStripListener = new FilmStripView.Listener() {
@Override
public void onDataPromoted(int dataID) {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_DELETE, "promoted", 0,
UsageStatistics.hashFileName(fileNameFromDataID(dataID)));
removeData(dataID);
}
@Override
public void onDataDemoted(int dataID) {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_DELETE, "demoted", 0,
UsageStatistics.hashFileName(fileNameFromDataID(dataID)));
removeData(dataID);
}
@Override
public void onDataFullScreenChange(int dataID, boolean full) {
boolean isCameraID = isCameraPreview(dataID);
Log.d(TAG, " full= " + full + " isCameraID= " + isCameraID
+ " dataID=" + dataID);
if (!isCameraID) {
if (!full) {
// Always show action bar in filmstrip mode
CameraActivity.this.setSystemBarsVisibility(true, false);
} else if (mActionBar.isShowing()) {
// Hide action bar after time out in full screen mode
mMainHandler.sendEmptyMessageDelayed(HIDE_ACTION_BAR,
SHOW_ACTION_BAR_TIMEOUT_MS);
}
}
}
/**
* Check if the local data corresponding to dataID is the camera
* preview.
*
* @param dataID
* the ID of the local data
* @return true if the local data is not null and it is the camera
* preview.
*/
private boolean isCameraPreview(int dataID) {
LocalData localData = mDataAdapter.getLocalData(dataID);
if (localData == null) {
Log.w(TAG, "Current data ID not found.");
return false;
}
return localData.getLocalDataType() == LocalData.LOCAL_CAMERA_PREVIEW;
}
@Override
public void onReload() {
if (!mFilmStripView.isCameraPreview()) {
// For now, We ignore all items that are not the camera preview.
Log.d(TAG,
"onReload called not in camera preview ,PreviewControls not need show");
return;
}
setPreviewControlsVisibility(true);
CameraActivity.this.setSystemBarsVisibility(false);
}
@Override
public void onCurrentDataCentered(int dataID) {
if (dataID != 0 && !mFilmStripView.isCameraPreview()) {
// For now, We ignore all items that are not the camera preview.
return;
}
if (!arePreviewControlsVisible()) {
setPreviewControlsVisibility(true);
CameraActivity.this.setSystemBarsVisibility(false);
setModuleVisble(View.VISIBLE);
}
}
@Override
public void onCurrentDataOffCentered(int dataID) {
// SPRD: bug 266132
setModuleVisble(View.INVISIBLE);
if (dataID != 0 && !mFilmStripView.isCameraPreview()) {
// For now, We ignore all items that are not the camera preview.
return;
}
if (arePreviewControlsVisible()) {
setPreviewControlsVisibility(false);
}
}
@Override
public void onDataFocusChanged(final int dataID, final boolean focused) {
// Delay hiding action bar if there is any user interaction
if (mMainHandler.hasMessages(HIDE_ACTION_BAR)) {
mMainHandler.removeMessages(HIDE_ACTION_BAR);
mMainHandler.sendEmptyMessageDelayed(HIDE_ACTION_BAR,
SHOW_ACTION_BAR_TIMEOUT_MS);
}
// TODO: This callback is UI event callback, should always
// happen on UI thread. Find the reason for this
// runOnUiThread() and fix it.
runOnUiThread(new Runnable() {
@Override
public void run() {
LocalData currentData = mDataAdapter.getLocalData(dataID);
if (currentData == null) {
Log.w(TAG, "Current data ID not found.");
hidePanoStitchingProgress();
return;
}
boolean isCameraID = currentData.getLocalDataType() == LocalData.LOCAL_CAMERA_PREVIEW;
if (!focused) {
if (isCameraID) {
mCurrentModule.onPreviewFocusChanged(false);
CameraActivity.this.setSystemBarsVisibility(true);
}
hidePanoStitchingProgress();
} else {
if (isCameraID) {
// Don't show the action bar in Camera
// preview.
mCurrentModule.onPreviewFocusChanged(true);
CameraActivity.this.setSystemBarsVisibility(false);
if (mPendingDeletion) {
performDeletion();
}
} else {
updateActionBarMenu(dataID);
}
Uri contentUri = currentData.getContentUri();
if (contentUri == null) {
hidePanoStitchingProgress();
return;
}
int panoStitchingProgress = mPanoramaManager
.getTaskProgress(contentUri);
if (panoStitchingProgress < 0) {
hidePanoStitchingProgress();
return;
}
showPanoStitchingProgress();
updateStitchingProgress(panoStitchingProgress);
}
}
});
}
@Override
public void onToggleSystemDecorsVisibility(int dataID) {
// If action bar is showing, hide it immediately, otherwise
// show action bar and hide it later
if (mActionBar.isShowing()) {
CameraActivity.this.setSystemBarsVisibility(false);
} else {
// Don't show the action bar if that is the camera preview.
boolean isCameraID = isCameraPreview(dataID);
if (!isCameraID) {
CameraActivity.this.setSystemBarsVisibility(true, true);
}
}
}
@Override
public void setSystemDecorsVisibility(boolean visible) {
CameraActivity.this.setSystemBarsVisibility(visible);
}
};
public void gotoGallery() {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_FILMSTRIP, "thumbnailTap");
mFilmStripView.getController().goToNextItem();
}
/**
* If
*
* @param visible
* is false, this hides the action bar and switches the system UI
* to lights-out mode.
*/
// TODO: This should not be called outside of the activity.
public void setSystemBarsVisibility(boolean visible) {
setSystemBarsVisibility(visible, false);
}
/**
* If
*
* @param visible
* is false, this hides the action bar and switches the system UI
* to lights-out mode. If
* @param hideLater
* is true, a delayed message will be sent after a timeout to
* hide the action bar.
*/
private void setSystemBarsVisibility(boolean visible, boolean hideLater) {
mMainHandler.removeMessages(HIDE_ACTION_BAR);
int currentSystemUIVisibility = mAboveFilmstripControlLayout
.getSystemUiVisibility();
int newSystemUIVisibility = DEFAULT_SYSTEM_UI_VISIBILITY
| (visible ? View.SYSTEM_UI_FLAG_VISIBLE
: View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN);
if (newSystemUIVisibility != currentSystemUIVisibility) {
mAboveFilmstripControlLayout
.setSystemUiVisibility(newSystemUIVisibility);
}
boolean currentActionBarVisibility = mActionBar.isShowing();
if (visible != currentActionBarVisibility) {
if (visible) {
mActionBar.show();
} else {
mActionBar.hide();
}
if (mOnActionBarVisibilityListener != null) {
mOnActionBarVisibilityListener
.onActionBarVisibilityChanged(visible);
}
}
// Now delay hiding the bars
if (visible && hideLater) {
mMainHandler.sendEmptyMessageDelayed(HIDE_ACTION_BAR,
SHOW_ACTION_BAR_TIMEOUT_MS);
}
}
private void hidePanoStitchingProgress() {
mPanoStitchingPanel.setVisibility(View.GONE);
}
private void showPanoStitchingProgress() {
mPanoStitchingPanel.setVisibility(View.VISIBLE);
}
private void updateStitchingProgress(int progress) {
mBottomProgress.setProgress(progress);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setupNfcBeamPush() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(CameraActivity.this);
if (adapter == null) {
return;
}
if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) {
// Disable beaming
adapter.setNdefPushMessage(null, CameraActivity.this);
return;
}
adapter.setBeamPushUris(null, CameraActivity.this);
adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
@Override
public Uri[] createBeamUris(NfcEvent event) {
return mNfcPushUris;
}
}, CameraActivity.this);
}
private void setNfcBeamPushUri(Uri uri) {
mNfcPushUris[0] = uri;
}
private void setStandardShareIntent(Uri contentUri, String mimeType) {
mStandardShareIntent = getShareIntentFromType(mimeType);
if (mStandardShareIntent != null) {
mStandardShareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
mStandardShareIntent
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (mStandardShareActionProvider != null) {
mStandardShareActionProvider
.setShareIntent(mStandardShareIntent);
}
}
}
/**
* Get the share intent according to the mimeType
*
* @param mimeType
* The mimeType of current data.
* @return the video/image's ShareIntent or null if mimeType is invalid.
*/
private Intent getShareIntentFromType(String mimeType) {
// Lazily create the intent object.
if (mimeType.startsWith("video/")) {
if (mVideoShareIntent == null) {
mVideoShareIntent = new Intent(Intent.ACTION_SEND);
mVideoShareIntent.setType("video/*");
}
return mVideoShareIntent;
} else if (mimeType.startsWith("image/")) {
if (mImageShareIntent == null) {
mImageShareIntent = new Intent(Intent.ACTION_SEND);
mImageShareIntent.setType("image/*");
}
return mImageShareIntent;
}
Log.w(TAG, "unsupported mimeType " + mimeType);
return null;
}
private void setPanoramaShareIntent(Uri contentUri) {
if (mPanoramaShareIntent == null) {
mPanoramaShareIntent = new Intent(Intent.ACTION_SEND);
}
mPanoramaShareIntent.setType("application/vnd.google.panorama360+jpg");
mPanoramaShareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
if (mPanoramaShareActionProvider != null) {
mPanoramaShareActionProvider.setShareIntent(mPanoramaShareIntent);
}
}
@Override
public void onMenuVisibilityChanged(boolean isVisible) {
// If menu is showing, we need to make sure action bar does not go away.
mMainHandler.removeMessages(HIDE_ACTION_BAR);
if (!isVisible) {
mMainHandler.sendEmptyMessageDelayed(HIDE_ACTION_BAR,
SHOW_ACTION_BAR_TIMEOUT_MS);
}
}
@Override
public boolean onShareTargetSelected(
ShareActionProvider shareActionProvider, Intent intent) {
int currentDataId = mFilmStripView.getCurrentId();
if (currentDataId < 0) {
return false;
}
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_SHARE, intent.getComponent()
.getPackageName(), 0, UsageStatistics
.hashFileName(fileNameFromDataID(currentDataId)));
return true;
}
/**
* According to the data type, make the menu items for supported operations
* visible.
*
* @param dataID
* the data ID of the current item.
*/
private void updateActionBarMenu(int dataID) {
LocalData currentData = mDataAdapter.getLocalData(dataID);
if (currentData == null) {
return;
}
int type = currentData.getLocalDataType();
if (mActionBarMenu == null) {
return;
}
int supported = 0;
switch (type) {
case LocalData.LOCAL_IMAGE:
supported |= SUPPORT_DELETE | SUPPORT_ROTATE | SUPPORT_INFO
| SUPPORT_CROP | SUPPORT_SETAS | SUPPORT_EDIT
| SUPPORT_SHARE | SUPPORT_SHOW_ON_MAP;
break;
case LocalData.LOCAL_VIDEO:
supported |= SUPPORT_DELETE | SUPPORT_INFO | SUPPORT_TRIM
| SUPPORT_SHARE;
break;
case LocalData.LOCAL_PHOTO_SPHERE:
supported |= SUPPORT_DELETE | SUPPORT_ROTATE | SUPPORT_INFO
| SUPPORT_CROP | SUPPORT_SETAS | SUPPORT_EDIT
| SUPPORT_SHARE | SUPPORT_SHOW_ON_MAP;
break;
case LocalData.LOCAL_360_PHOTO_SPHERE:
supported |= SUPPORT_DELETE | SUPPORT_ROTATE | SUPPORT_INFO
| SUPPORT_CROP | SUPPORT_SETAS | SUPPORT_EDIT
| SUPPORT_SHARE | SUPPORT_SHARE_PANORAMA360
| SUPPORT_SHOW_ON_MAP;
break;
default:
break;
}
// In secure camera mode, we only support delete operation.
if (isSecureCamera()) {
supported &= SUPPORT_DELETE;
}
setMenuItemVisible(mActionBarMenu, R.id.action_delete,
(supported & SUPPORT_DELETE) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_rotate_ccw,
(supported & SUPPORT_ROTATE) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_rotate_cw,
(supported & SUPPORT_ROTATE) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_details,
(supported & SUPPORT_INFO) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_crop,
(supported & SUPPORT_CROP) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_setas,
(supported & SUPPORT_SETAS) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_edit,
(supported & SUPPORT_EDIT) != 0);
setMenuItemVisible(mActionBarMenu, R.id.action_trim,
(supported & SUPPORT_TRIM) != 0);
boolean standardShare = (supported & SUPPORT_SHARE) != 0;
boolean panoramaShare = (supported & SUPPORT_SHARE_PANORAMA360) != 0;
setMenuItemVisible(mActionBarMenu, R.id.action_share, standardShare);
setMenuItemVisible(mActionBarMenu, R.id.action_share_panorama,
panoramaShare);
if (panoramaShare) {
// For 360 PhotoSphere, relegate standard share to the overflow menu
MenuItem item = mActionBarMenu.findItem(R.id.action_share);
if (item != null) {
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
item.setTitle(getResources().getString(R.string.share_as_photo));
}
// And, promote "share as panorama" to action bar
item = mActionBarMenu.findItem(R.id.action_share_panorama);
if (item != null) {
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
setPanoramaShareIntent(currentData.getContentUri());
}
if (standardShare) {
if (!panoramaShare) {
MenuItem item = mActionBarMenu.findItem(R.id.action_share);
if (item != null) {
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
item.setTitle(getResources().getString(R.string.share));
}
}
setStandardShareIntent(currentData.getContentUri(),
currentData.getMimeType());
setNfcBeamPushUri(currentData.getContentUri());
}
boolean itemHasLocation = currentData.getLatLong() != null;
setMenuItemVisible(mActionBarMenu, R.id.action_show_on_map,
itemHasLocation && (supported & SUPPORT_SHOW_ON_MAP) != 0);
}
private void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
MenuItem item = menu.findItem(itemId);
if (item != null)
item.setVisible(visible);
}
private ImageTaskManager.TaskListener mPlaceholderListener = new ImageTaskManager.TaskListener() {
@Override
public void onTaskQueued(String filePath, final Uri imageUri) {
mMainHandler.post(new Runnable() {
@Override
public void run() {
notifyNewMedia(imageUri);
int dataID = mDataAdapter.findDataByContentUri(imageUri);
if (dataID != -1) {
LocalData d = mDataAdapter.getLocalData(dataID);
InProgressDataWrapper newData = new InProgressDataWrapper(
d, true);
mDataAdapter.updateData(dataID, newData);
}
}
});
}
@Override
public void onTaskDone(String filePath, final Uri imageUri) {
mMainHandler.post(new Runnable() {
@Override
public void run() {
mDataAdapter.refresh(getContentResolver(), imageUri);
}
});
}
@Override
public void onTaskProgress(String filePath, Uri imageUri, int progress) {
// Do nothing
}
};
private ImageTaskManager.TaskListener mStitchingListener = new ImageTaskManager.TaskListener() {
@Override
public void onTaskQueued(String filePath, final Uri imageUri) {
mMainHandler.post(new Runnable() {
@Override
public void run() {
notifyNewMedia(imageUri);
int dataID = mDataAdapter.findDataByContentUri(imageUri);
if (dataID != -1) {
// Don't allow special UI actions (swipe to
// delete, for example) on in-progress data.
LocalData d = mDataAdapter.getLocalData(dataID);
InProgressDataWrapper newData = new InProgressDataWrapper(
d);
mDataAdapter.updateData(dataID, newData);
}
}
});
}
@Override
public void onTaskDone(String filePath, final Uri imageUri) {
Log.v(TAG, "onTaskDone:" + filePath);
mMainHandler.post(new Runnable() {
@Override
public void run() {
int doneID = mDataAdapter.findDataByContentUri(imageUri);
int currentDataId = mFilmStripView.getCurrentId();
if (currentDataId == doneID) {
hidePanoStitchingProgress();
updateStitchingProgress(0);
}
mDataAdapter.refresh(getContentResolver(), imageUri);
}
});
}
@Override
public void onTaskProgress(String filePath, final Uri imageUri,
final int progress) {
mMainHandler.post(new Runnable() {
@Override
public void run() {
int currentDataId = mFilmStripView.getCurrentId();
if (currentDataId == -1) {
return;
}
if (imageUri.equals(mDataAdapter
.getLocalData(currentDataId).getContentUri())) {
updateStitchingProgress(progress);
}
}
});
}
};
public MediaSaveService getMediaSaveService() {
return mMediaSaveService;
}
public void notifyNewMedia(Uri uri) {
ContentResolver cr = getContentResolver();
/**
* SPRD: if remove sd card while videorecording,the extension of
* recording file maybe .mp4.tmp not a valid video file,and its
* mine_type in database is null, need to catch this Exception @
*/
String mimeType = null;
try {
mimeType = cr.getType(uri);
} catch (IllegalStateException e) {
Log.e(TAG, "Unknown URL or mimeType is null:" + uri);
}
if (mimeType == null)
return;
/** }@ */
if (mimeType.startsWith("video/")) {
sendBroadcast(new Intent(CameraUtil.ACTION_NEW_VIDEO, uri));
mDataAdapter.addNewVideo(cr, uri);
} else if (mimeType.startsWith("image/")) {
CameraUtil.broadcastNewPicture(this, uri);
mDataAdapter.addNewPhoto(cr, uri);
} else if (mimeType.startsWith("application/stitching-preview")) {
mDataAdapter.addNewPhoto(cr, uri);
} else if (mimeType
.startsWith(PlaceholderManager.PLACEHOLDER_MIME_TYPE)) {
mDataAdapter.addNewPhoto(cr, uri);
} else {
android.util.Log.w(TAG, "Unknown new media with MIME type:"
+ mimeType + ", uri:" + uri);
}
}
private void removeData(int dataID) {
Log.d(TAG, "#removeData dataID==" + dataID);
if (mFilmStripView != null) {
mFilmStripView.resetZoomView(true);
}
mDataAdapter.removeData(CameraActivity.this, dataID);
if (dataID == 1) {
mMainHandler.sendEmptyMessage(UPDATE_THUMBAIL);
}
if (mDataAdapter.getTotalNumber() > 1) {
showUndoDeletionBar();
} else {
// If camera preview is the only view left in filmstrip,
// no need to show undo bar.
mPendingDeletion = true;
performDeletion();
}
}
private void bindMediaSaveService() {
Intent intent = new Intent(this, MediaSaveService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
private void unbindMediaSaveService() {
if (mConnection != null) {
unbindService(mConnection);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.operations, menu);
/** SPRD: skip trim and mute menu item for bug 273733 @{ */
if (!mTrimvideoEnable) {
menu.removeItem(R.id.action_trim);
}
/** @} */
mActionBarMenu = menu;
// Configure the standard share action provider
MenuItem item = menu.findItem(R.id.action_share);
mStandardShareActionProvider = (ShareActionProvider) item
.getActionProvider();
mStandardShareActionProvider
.setShareHistoryFileName("standard_share_history.xml");
if (mStandardShareIntent != null) {
mStandardShareActionProvider.setShareIntent(mStandardShareIntent);
}
// Configure the panorama share action provider
item = menu.findItem(R.id.action_share_panorama);
mPanoramaShareActionProvider = (ShareActionProvider) item
.getActionProvider();
mPanoramaShareActionProvider
.setShareHistoryFileName("panorama_share_history.xml");
if (mPanoramaShareIntent != null) {
mPanoramaShareActionProvider.setShareIntent(mPanoramaShareIntent);
}
mStandardShareActionProvider.setOnShareTargetSelectedListener(this);
mPanoramaShareActionProvider.setOnShareTargetSelectedListener(this);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int currentDataId = mFilmStripView.getCurrentId();
if (currentDataId < 0) {
return false;
}
final LocalData localData = mDataAdapter.getLocalData(currentDataId);
// Handle presses on the action bar items
switch (item.getItemId()) {
case android.R.id.home:
// ActionBar's Up/Home button was clicked
try {
startActivity(IntentHelper.getGalleryIntent(this));
return true;
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Failed to launch gallery activity, closing");
finish();
}
case R.id.action_delete:
// add by topwise qiujq for bug503 start
new AlertDialog.Builder(this)
.setTitle(R.string.delete)
.setIcon(android.R.drawable.ic_dialog_alert)
// .setMessage(R.string.delete)
.setPositiveButton(R.string.dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
UsageStatistics.onEvent(
UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_DELETE,
null,
0,
UsageStatistics
.hashFileName(fileNameFromDataID(currentDataId)));
removeData(currentDataId);
}
}).setNegativeButton(R.string.dialog_cancel, null)
.show();
// add by topwise qiujq for bug503 end
/*
* deleted by topwise qiujq for bug503
* UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
* UsageStatistics.ACTION_DELETE, null, 0,
* UsageStatistics.hashFileName(fileNameFromDataID(currentDataId)));
* removeData(currentDataId);
*/
return true;
case R.id.action_edit:
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_EDIT, null, 0, UsageStatistics
.hashFileName(fileNameFromDataID(currentDataId)));
launchEditor(localData);
return true;
case R.id.action_trim: {
// SPRD: catch ActivityNotFoundException
try {
// This is going to be handled by the Gallery app.
Intent intent = new Intent(ACTION_TRIM_VIDEO);
LocalData currentData = mDataAdapter
.getLocalData(mFilmStripView.getCurrentId());
intent.setData(currentData.getContentUri());
// We need the file path to wrap this into a RandomAccessFile.
intent.putExtra(MEDIA_ITEM_PATH, currentData.getPath());
startActivityForResult(intent, REQ_CODE_DONT_SWITCH_TO_PREVIEW);
} catch (ActivityNotFoundException e) {
CameraUtil.P(DEBUG, TAG, "activity not found exception e="
+ (e != null ? e.toString() : e));
}
return true;
}
case R.id.action_rotate_ccw:
localData.rotate90Degrees(this, mDataAdapter, currentDataId, false);
return true;
case R.id.action_rotate_cw:
localData.rotate90Degrees(this, mDataAdapter, currentDataId, true);
return true;
case R.id.action_crop: {
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_CROP, null, 0, UsageStatistics
.hashFileName(fileNameFromDataID(currentDataId)));
Intent intent = new Intent(CropActivity.CROP_ACTION);
intent.setClass(this, CropActivity.class);
intent.setDataAndType(localData.getContentUri(),
localData.getMimeType()).setFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, REQ_CODE_DONT_SWITCH_TO_PREVIEW);
return true;
}
case R.id.action_setas: {
Intent intent = new Intent(Intent.ACTION_ATTACH_DATA)
.setDataAndType(localData.getContentUri(),
localData.getMimeType()).setFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("mimeType", intent.getType());
startActivityForResult(
Intent.createChooser(intent, getString(R.string.set_as)),
REQ_CODE_DONT_SWITCH_TO_PREVIEW);
return true;
}
case R.id.action_details:
(new AsyncTask<Void, Void, MediaDetails>() {
@Override
protected MediaDetails doInBackground(Void... params) {
return localData.getMediaDetails(CameraActivity.this);
}
@Override
protected void onPostExecute(MediaDetails mediaDetails) {
if (mediaDetails != null) {
DetailsDialog.create(CameraActivity.this, mediaDetails)
.show();
}
}
}).execute();
return true;
case R.id.action_show_on_map:
double[] latLong = localData.getLatLong();
if (latLong != null) {
CameraUtil.showOnMap(this, latLong);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private boolean isCaptureIntent() {
if (MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())
|| MediaStore.ACTION_IMAGE_CAPTURE.equals(getIntent()
.getAction())
|| MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(getIntent()
.getAction())) {
return true;
} else {
return false;
}
}
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
GcamHelper.init(getContentResolver());
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.camera_filmstrip);
mActionBar = getActionBar();
mActionBar.addOnMenuVisibilityListener(this);
if (ApiHelper.HAS_ROTATION_ANIMATION) {
setRotationAnimation();
}
mMainHandler = new MainHandler(getMainLooper());
// Check if this is in the secure camera mode.
Intent intent = getIntent();
String action = intent.getAction();
bCameraButtonStart = intent.getBooleanExtra(MEDIA_CAMERA_BUTTON_START,
false);
if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)
|| ACTION_IMAGE_CAPTURE_SECURE.equals(action)) {
mSecureCamera = true;
} else {
mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
}
IntentFilter shutdownfilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
shutdownfilter.setPriority(Integer.MAX_VALUE);
registerReceiver(mShutDownReceiver, shutdownfilter);
// @{ SPRD: receive storage intent broadcast begin
IntentFilter mFilter = new IntentFilter();
mFilter.addAction("android.intent.action.MEDIA_SHARED");
mFilter.addAction("android.intent.action.MEDIA_MOUNTED");
mFilter.addAction("android.intent.action.MEDIA_UNMOUNTED");
mFilter.addDataScheme("file");
registerReceiver(mStorageReceiver, mFilter);
// SPRD: receive storage intent broadcast end @}
if (mSecureCamera) {
// Change the window flags so that secure camera can show when
// locked
Window win = getWindow();
WindowManager.LayoutParams params = win.getAttributes();
params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
win.setAttributes(params);
// Filter for screen off so that we can finish secure camera
// activity
// when screen is off.
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenOffReceiver, filter);
// TODO: This static screen off event receiver is a workaround to
// the
// double onResume() invocation (onResume->onPause->onResume). We
// should
// find a better solution to this.
if (sScreenOffReceiver == null) {
sScreenOffReceiver = new ScreenOffReceiver();
registerReceiver(sScreenOffReceiver, filter);
}
}
mAboveFilmstripControlLayout = (FrameLayout) findViewById(R.id.camera_above_filmstrip_layout);
mAboveFilmstripControlLayout.setFitsSystemWindows(true);
// Hide action bar first since we are in full screen mode first, and
// switch the system UI to lights-out mode.
this.setSystemBarsVisibility(false);
mPanoramaManager = AppManagerFactory.getInstance(this)
.getPanoramaStitchingManager();
mPlaceholderManager = AppManagerFactory.getInstance(this)
.getGcamProcessingManager();
mPanoramaManager.addTaskListener(mStitchingListener);
mPlaceholderManager.addTaskListener(mPlaceholderListener);
LayoutInflater inflater = getLayoutInflater();
View rootLayout = inflater.inflate(R.layout.camera, null, false);
mFilmStripView = (ScrollFilmStripView) findViewById(R.id.filmstrip_view);
mCameraModuleRootView = rootLayout.findViewById(R.id.camera_app_root);
mPanoStitchingPanel = findViewById(R.id.pano_stitching_progress_panel);
mBottomProgress = (ProgressBar) findViewById(R.id.pano_stitching_progress_bar);
mCameraPreviewData = new CameraPreviewData(rootLayout,
FilmStripView.ImageData.SIZE_FULL,
FilmStripView.ImageData.SIZE_FULL);
mFilmStripView.setViewGap(getResources().getDimensionPixelSize(
R.dimen.camera_film_strip_gap));
mPanoramaViewHelper = new PanoramaViewHelper(this);
mPanoramaViewHelper.onCreate();
mFilmStripView.setPanoramaViewHelper(mPanoramaViewHelper);
// Set up the camera preview first so the preview shows up ASAP.
mFilmStripView.setListener(mFilmStripListener);
int moduleIndex = -1;
if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent()
.getAction())
|| MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent()
.getAction())) {
moduleIndex = ModuleSwitcher.VIDEO_MODULE_INDEX;
} else if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
.equals(getIntent().getAction())
|| MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
.equals(getIntent().getAction())) {
moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
if (prefs.getInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, -1) == ModuleSwitcher.GCAM_MODULE_INDEX
&& GcamHelper.hasGcamCapture()) {
moduleIndex = ModuleSwitcher.GCAM_MODULE_INDEX;
}
} else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(getIntent()
.getAction())
|| MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(getIntent()
.getAction())) {
moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
} else {
// If the activity has not been started using an explicit intent,
// read the module index from the last time the user changed modes
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
try{
moduleIndex = prefs.getInt(CameraSettings.KEY_STARTUP_MODULE_INDEX,
-1);
}catch(Exception e){
moduleIndex=-1;
}
if ((moduleIndex == ModuleSwitcher.GCAM_MODULE_INDEX && !GcamHelper
.hasGcamCapture()) || moduleIndex < 0) {
moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
}
}
// Put a CameraPreviewData at the first position.
mWrappedDataAdapter = new FixedFirstDataAdapter(new CameraDataAdapter(
new ColorDrawable(getResources().getColor(
R.color.photo_placeholder)), moduleIndex),
mCameraPreviewData);
mOrientationListener = new MyOrientationEventListener(this);
setModuleFromIndex(moduleIndex);
mCurrentModule.init(this, mCameraModuleRootView);
if (!mSecureCamera) {
mDataAdapter = mWrappedDataAdapter;
mFilmStripView.setDataAdapter(mDataAdapter);
if (!isCaptureIntent()) {
updateDataAdapter(false);
}
} else {
// Put a lock placeholder as the last image by setting its date to
// 0.
ImageView v = (ImageView) getLayoutInflater().inflate(
R.layout.secure_album_placeholder, null);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
UsageStatistics.onEvent(
UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_GALLERY, null);
startActivity(IntentHelper
.getGalleryIntent(CameraActivity.this));
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Failed to launch gallery activity, closing");
}
finish();
}
});
mDataAdapter = new FixedLastDataAdapter(mWrappedDataAdapter,
new SimpleViewData(v, v.getDrawable().getIntrinsicWidth(),
v.getDrawable().getIntrinsicHeight(), 0, 0));
// Flush out all the original data.
mDataAdapter.flush();
mFilmStripView.setDataAdapter(mDataAdapter);
}
setupNfcBeamPush();
mLocalImagesObserver = new LocalMediaObserver();
mLocalVideosObserver = new LocalMediaObserver();
getContentResolver().registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true,
mLocalImagesObserver);
getContentResolver().registerContentObserver(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true,
mLocalVideosObserver);
getContentResolver().registerContentObserver(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true,
mMediaChangeObserver);
}
private void setRotationAnimation() {
int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
Window win = getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
winParams.rotationAnimation = rotationAnimation;
win.setAttributes(winParams);
}
@Override
public void onUserInteraction() {
super.onUserInteraction();
mCurrentModule.onUserInteraction();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean result = super.dispatchTouchEvent(ev);
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
// Real deletion is postponed until the next user interaction after
// the gesture that triggers deletion. Until real deletion is
// performed,
// users can click the undo button to bring back the image that they
// chose to delete.
if (mPendingDeletion && !mIsUndoingDeletion) {
performDeletion();
}
}
return result;
}
@Override
public void onPause() {
// Delete photos that are pending deletion
Log.d(TAG, "performance: onPause is pressed start......");
performDeletion();
mOrientationListener.disable();
mCurrentModule.onPauseBeforeSuper();
super.onPause();
mCurrentModule.onPauseAfterSuper();
saveLastThumbnailPath();
mLocalImagesObserver.setActivityPaused(true);
mLocalVideosObserver.setActivityPaused(true);
Log.d(TAG, "performance: onPause is pressed end......");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQ_CODE_DONT_SWITCH_TO_PREVIEW) {
mResetToPreviewOnResume = false;
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onResume() {
// TODO: Handle this in OrientationManager.
// Auto-rotate off
Log.d(TAG, "performance: onResume is pressed start......");
if (Settings.System.getInt(getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
mAutoRotateScreen = false;
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
mAutoRotateScreen = true;
}
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_FOREGROUNDED, this.getClass()
.getSimpleName());
mOrientationListener.enable();
initLastThumbnailPath();
firstTimeUpdateThumbnail();
mCurrentModule.onResumeBeforeSuper();
super.onResume();
mCurrentModule.onResumeAfterSuper();
setSwipingEnabled(true);
if (mResetToPreviewOnResume) {
// Go to the preview on resume.
mFilmStripView.getController().goToFirstItem();
}
// Default is showing the preview, unless disabled by explicitly
// starting an activity we want to return from to the filmstrip rather
// than the preview.
mResetToPreviewOnResume = true;
/*
* SPRD: fixbug263739 setModuleView invisible if not in camera preview
* @{
*/
if (mFilmStripView.isCameraPreview()) {
mCurrentModule.showControls();
}
/* @} */
if (mLocalVideosObserver.isMediaDataChangedDuringPause()
|| mLocalImagesObserver.isMediaDataChangedDuringPause()) {
if (!mSecureCamera) {
// If it's secure camera, requestLoad() should not be called
// as it will load all the data.
updateDataAdapter(false);
}
}
mLocalImagesObserver.setActivityPaused(false);
mLocalVideosObserver.setActivityPaused(false);
// SPRD: If mAdapter is null Init StorageUtil update that here
if (mNeedUpdatPath) {
mNeedUpdatPath = false;
UpdatPath();
}
Log.d(TAG, "performance: onResume is pressed end......");
}
@Override
public void onStart() {
Log.v(TAG, "performance: onStart start..... ");
super.onStart();
bindMediaSaveService();
mPanoramaViewHelper.onStart();
Log.v(TAG, "performance: onStart end..... ");
}
@Override
protected void onStop() {
Log.v(TAG, "performance: onStop start..... ");
super.onStop();
mPanoramaViewHelper.onStop();
unbindMediaSaveService();
Log.v(TAG, "performance: onStop end..... ");
}
@Override
public void onDestroy() {
Log.v(TAG, "performance: onDestroy start..... ");
if (mSecureCamera) {
unregisterReceiver(mScreenOffReceiver);
}
unregisterReceiver(mStorageReceiver);
unregisterReceiver(mShutDownReceiver);
getContentResolver().unregisterContentObserver(mLocalImagesObserver);
getContentResolver().unregisterContentObserver(mLocalVideosObserver);
getContentResolver().unregisterContentObserver(mMediaChangeObserver);
super.onDestroy();
Log.v(TAG, "performance: onDestroy end..... ");
}
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
mCurrentModule.onConfigurationChanged(config);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// SPRD: bug 259407
if (mFilmStripView.isCameraPreview()) {
/** SPRD: fixbug255613 if in CameraPreview,set menu keyevent return @{ */
if (keyCode == KeyEvent.KEYCODE_MENU) {
return true;
}
/** fixbug255613 end @} */
if (mCurrentModule.onKeyDown(keyCode, event)) {
return true;
}
// Prevent software keyboard or voice search from showing up.
if (keyCode == KeyEvent.KEYCODE_SEARCH
|| keyCode == KeyEvent.KEYCODE_MENU) {
if (event.isLongPress()) {
return true;
}
}
} else {
if (keyCode == KeyEvent.KEYCODE_MENU) {
CameraActivity.this.setSystemBarsVisibility(true);
if (mPendingDeletion && !mIsUndoingDeletion) {
Log.d(TAG, "KEYCODE_MENU down call performDeletion");
performDeletion();
}
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mFilmStripView.inCameraFullscreen() && !bCameraButtonStart
&& mCurrentModule.onKeyUp(keyCode, event)) {
return true;
}
bCameraButtonStart = false;
return super.onKeyUp(keyCode, event);
}
@Override
public void onBackPressed() {
Log.d(TAG, "performance: onBackPressed is pressed start......");
if (!mFilmStripView.inCameraFullscreen()) {
setModuleVisble(View.VISIBLE);
mFilmStripView.getController().goToFirstItem();
} else if (!mCurrentModule.onBackPressed()) {
super.onBackPressed();
}
Log.d(TAG, "performance: onBackPressed is pressed end......");
}
public boolean isAutoRotateScreen() {
return mAutoRotateScreen;
}
protected void updateStorageSpace() {
// mStorageSpaceBytes = Storage.getAvailableSpace();
int mode = CameraUtil.MODE_VIDEO;
if (ModuleSwitcher.VIDEO_MODULE_INDEX != mCurrentModuleIndex) {
mode = CameraUtil.MODE_CAMERA;
}
StorageUtil util = StorageUtil.newInstance();
util.getStoragePath(this, mode);
if (isCaptureIntent()
&& (getIntent().hasExtra(MediaStore.EXTRA_OUTPUT))) {
mStorageSpaceBytes = util.getInternalAvailableSpace();
} else {
mStorageSpaceBytes = util.getAvailableSpace(mode);
}
}
protected long getStorageSpaceBytes() {
return mStorageSpaceBytes;
}
protected void updateStorageSpaceAndHint() {
updateStorageSpace();
updateStorageHint(mStorageSpaceBytes);
}
protected void updateStorageHint(long storageSpace) {
String message = null;
if (storageSpace == Storage.UNAVAILABLE) {
message = getString(R.string.no_storage);
} else if (storageSpace == Storage.PREPARING) {
message = getString(R.string.preparing_sd);
} else if (storageSpace == Storage.UNKNOWN_SIZE) {
message = getString(R.string.access_sd_fail);
} else if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
message = getString(R.string.spaceIsLow_content);
}
if (message != null) {
if (mStorageHint == null) {
mStorageHint = OnScreenHint.makeText(this, message);
} else {
mStorageHint.setText(message);
}
mStorageHint.show();
} else if (mStorageHint != null) {
mStorageHint.cancel();
mStorageHint = null;
}
}
protected void setResultEx(int resultCode) {
mResultCodeForTesting = resultCode;
setResult(resultCode);
}
protected void setResultEx(int resultCode, Intent data) {
mResultCodeForTesting = resultCode;
mResultDataForTesting = data;
setResult(resultCode, data);
}
public int getResultCode() {
return mResultCodeForTesting;
}
public Intent getResultData() {
return mResultDataForTesting;
}
public boolean isSecureCamera() {
return mSecureCamera;
}
@Override
public void onModuleSelected(int moduleIndex) {
if (mCurrentModuleIndex == moduleIndex) {
return;
}
CameraHolder.instance().keep();
closeModule(mCurrentModule);
setModuleFromIndex(moduleIndex);
openModule(mCurrentModule);
mCurrentModule.onOrientationChanged(mLastRawOrientation);
if (mMediaSaveService != null) {
mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
}
// Store the module index so we can use it the next time the Camera
// starts up.
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
prefs.edit()
.putInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, moduleIndex)
.apply();
}
/**
* Sets the mCurrentModuleIndex, creates a new module instance for the given
* index an sets it as mCurrentModule.
*/
private void setModuleFromIndex(int moduleIndex) {
mCurrentModuleIndex = moduleIndex;
switch (moduleIndex) {
case ModuleSwitcher.VIDEO_MODULE_INDEX:
mCurrentModule = new VideoModule();
break;
case ModuleSwitcher.PHOTO_MODULE_INDEX:
mCurrentModule = new PhotoModule();
break;
case ModuleSwitcher.WIDE_ANGLE_PANO_MODULE_INDEX:
mCurrentModule = new WideAnglePanoramaModule();
break;
case ModuleSwitcher.LIGHTCYCLE_MODULE_INDEX:
mCurrentModule = PhotoSphereHelper.createPanoramaModule();
break;
case ModuleSwitcher.GCAM_MODULE_INDEX:
// Force immediate release of Camera instance
CameraHolder.instance().strongRelease();
mCurrentModule = GcamHelper.createGcamModule();
break;
default:
// Fall back to photo mode.
mCurrentModule = new PhotoModule();
mCurrentModuleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
break;
}
}
/**
* Launches an ACTION_EDIT intent for the given local data item.
*/
public void launchEditor(LocalData data) {
if (data == null || data.getContentUri() == null)
return;
Intent intent = new Intent(Intent.ACTION_EDIT).setDataAndType(
data.getContentUri(), data.getMimeType()).setFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivityForResult(intent, REQ_CODE_DONT_SWITCH_TO_PREVIEW);
} catch (ActivityNotFoundException e) {
startActivityForResult(Intent.createChooser(intent, null),
REQ_CODE_DONT_SWITCH_TO_PREVIEW);
}
}
/**
* Launch the tiny planet editor.
*
* @param data
* the data must be a 360 degree stereographically mapped
* panoramic image. It will not be modified, instead a new item
* with the result will be added to the filmstrip.
*/
public void launchTinyPlanetEditor(LocalData data) {
TinyPlanetFragment fragment = new TinyPlanetFragment();
Bundle bundle = new Bundle();
bundle.putString(TinyPlanetFragment.ARGUMENT_URI, data.getContentUri()
.toString());
bundle.putString(TinyPlanetFragment.ARGUMENT_TITLE, data.getTitle());
fragment.setArguments(bundle);
fragment.show(getFragmentManager(), "tiny_planet");
}
private void openModule(CameraModule module) {
module.init(this, mCameraModuleRootView);
firstTimeUpdateThumbnail();
module.onResumeBeforeSuper();
module.onResumeAfterSuper();
}
private void closeModule(CameraModule module) {
module.onPauseBeforeSuper();
module.onPauseAfterSuper();
((ViewGroup) mCameraModuleRootView).removeAllViews();
}
private void performDeletion() {
if (!mPendingDeletion) {
return;
}
hideUndoDeletionBar(false);
mDataAdapter.executeDeletion(CameraActivity.this);
int currentId = mFilmStripView.getCurrentId();
updateActionBarMenu(currentId);
mFilmStripListener.onCurrentDataCentered(currentId);
}
public void showUndoDeletionBar() {
if (mPendingDeletion) {
performDeletion();
}
Log.v(TAG, "showing undo bar");
mPendingDeletion = true;
if (mUndoDeletionBar == null) {
ViewGroup v = (ViewGroup) getLayoutInflater().inflate(
R.layout.undo_bar, mAboveFilmstripControlLayout, true);
mUndoDeletionBar = (ViewGroup) v
.findViewById(R.id.camera_undo_deletion_bar);
View button = mUndoDeletionBar
.findViewById(R.id.camera_undo_deletion_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDataAdapter.undoDataRemoval();
hideUndoDeletionBar(true);
}
});
// Setting undo bar clickable to avoid touch events going through
// the bar to the buttons (eg. edit button, etc) underneath the bar.
mUndoDeletionBar.setClickable(true);
// When there is user interaction going on with the undo button, we
// do not want to hide the undo bar.
button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mIsUndoingDeletion = true;
} else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
mIsUndoingDeletion = false;
}
return false;
}
});
}
mUndoDeletionBar.setAlpha(0f);
mUndoDeletionBar.setVisibility(View.VISIBLE);
mUndoDeletionBar.animate().setDuration(200).alpha(1f).setListener(null)
.start();
}
private void hideUndoDeletionBar(boolean withAnimation) {
Log.v(TAG, "Hiding undo deletion bar");
mPendingDeletion = false;
if (mUndoDeletionBar != null) {
if (withAnimation) {
mUndoDeletionBar.animate().setDuration(200).alpha(0f)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// Do nothing.
}
@Override
public void onAnimationEnd(Animator animation) {
mUndoDeletionBar.setVisibility(View.GONE);
}
@Override
public void onAnimationCancel(Animator animation) {
// Do nothing.
}
@Override
public void onAnimationRepeat(Animator animation) {
// Do nothing.
}
}).start();
} else {
mUndoDeletionBar.setVisibility(View.GONE);
}
}
}
@Override
public void onShowSwitcherPopup() {
mCurrentModule.onShowSwitcherPopup();
}
/**
* Enable/disable swipe-to-filmstrip. Will always disable swipe if in
* capture intent.
*
* @param enable
* {@code true} to enable swipe.
*/
public void setSwipingEnabled(boolean enable) {
if (isCaptureIntent()) {
mCameraPreviewData.lockPreview(true);
} else {
mCameraPreviewData.lockPreview(!enable);
}
}
/**
* Check whether camera controls are visible.
*
* @return whether controls are visible.
*/
private boolean arePreviewControlsVisible() {
return mCurrentModule.arePreviewControlsVisible();
}
/**
* Show or hide the {@link CameraControls} using the current module's
* implementation of {@link #onPreviewFocusChanged}.
*
* @param showControls
* whether to show camera controls.
*/
private void setPreviewControlsVisibility(boolean showControls) {
mCurrentModule.onPreviewFocusChanged(showControls);
}
// Accessor methods for getting latency times used in performance testing
public long getAutoFocusTime() {
return (mCurrentModule instanceof PhotoModule) ? ((PhotoModule) mCurrentModule).mAutoFocusTime
: -1;
}
public long getShutterLag() {
return (mCurrentModule instanceof PhotoModule) ? ((PhotoModule) mCurrentModule).mShutterLag
: -1;
}
public long getShutterToPictureDisplayedTime() {
return (mCurrentModule instanceof PhotoModule) ? ((PhotoModule) mCurrentModule).mShutterToPictureDisplayedTime
: -1;
}
public long getPictureDisplayedToJpegCallbackTime() {
return (mCurrentModule instanceof PhotoModule) ? ((PhotoModule) mCurrentModule).mPictureDisplayedToJpegCallbackTime
: -1;
}
public long getJpegCallbackFinishTime() {
return (mCurrentModule instanceof PhotoModule) ? ((PhotoModule) mCurrentModule).mJpegCallbackFinishTime
: -1;
}
public long getCaptureStartTime() {
return (mCurrentModule instanceof PhotoModule) ? ((PhotoModule) mCurrentModule).mCaptureStartTime
: -1;
}
public boolean isRecording() {
return (mCurrentModule instanceof VideoModule) ? ((VideoModule) mCurrentModule)
.isRecording() : false;
}
public CameraOpenErrorCallback getCameraOpenErrorCallback() {
return mCameraOpenErrorCallback;
}
// For debugging purposes only.
public CameraModule getCurrentModule() {
return mCurrentModule;
}
/* SPRD: develop new feature ZSL. */
protected static final int KEY_MODE_ZSL = 1;
// onClick handler for R.id.btn_switch
@OnClickAttr
public void onSwitchButtonClicked(View v) {
mCurrentModule.onSwitchButtonClicked();
}
// onClick handler for R.id.btn_hdr
@OnClickAttr
public void onHdrButtonClicked(View v) {
mCurrentModule.onHdrButtonClicked();
}
// onClick handler for R.id.btn_flash
@OnClickAttr
public void onFlashButtonClicked(View v) {
mCurrentModule.onFlashButtonClicked();
}
// onClick handler for R.id.btn_camera_setting
@OnClickAttr
public void onCameraSettingClicked(View v) {
mCurrentModule.onCameraSettingClicked();
}
// onClick handler for 1st level popup title
@OnClickAttr
public void onSettingTitleClicked(View v) {
mCurrentModule.onSettingTitleClicked(v);
}
// onClick handler for btn_video_pause
@OnClickAttr
public void onPauseClicked(View v) {
mCurrentModule.onPauseClicked();
}
// onClick handler for btn_video_pause
@OnClickAttr
public void onStopClicked(View v) {
mCurrentModule.onStopClicked();
}
private class LoadThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
LocalData firstData = null;
public LoadThumbnailTask() {
}
@Override
protected Bitmap doInBackground(Void... params) {
// Load the thumbnail from the provider.
// @{ SPRD: bug 256269 get video thumbnail when at video module
// begin
long id;
int orientation;
if (mDataAdapter != null) {
firstData = mDataAdapter.getFirstData();
}
if (firstData == null) {
return null;
}
id = firstData.getContentId();
orientation = firstData.getOrientation();
Log.d(TAG, "Get video id for UpdataThum is " + id
+ " orientation is " + orientation);
return Thumbnail.getLastThumbnailFromContentResolver(
getContentResolver(), id, orientation, mCurrentModuleIndex);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
return;
}
if (firstData == null || bitmap != null) {
mCurrentModule.updateThumbnail(bitmap);
}
}
}
// @{ SPRD: Module switch use Gesture scroll begin
@Override
public void onModuleViewSelected(int i) {
// TODO Auto-generated method stub
if (mCurrentModuleIndex == i) {
return;
}
CameraHolder.instance().keep();
closeModule(mCurrentModule);
setModuleFromIndex(i);
openModule(mCurrentModule);
mCurrentModule.onOrientationChanged(mLastRawOrientation);
if (mMediaSaveService != null) {
mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
}
// Store the module index so we can use it the next time the Camera
// starts up.
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
prefs.edit().putInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, i).apply();
// SPRD: bug 256269
mDataAdapter.setAdapterModule(mCurrentModuleIndex);
UpdatPath();
}
@Override
public void onShowSwitcherViewPopup() {
// TODO Auto-generated method stub
} // @{ SPRD: Module switch use Gesture scroll end
private boolean mNeedUpdatPath;
// @{ SPRD: bug 256269 updata DataAdapter and Thum when module switch begin
@Override
public void UpdatPath() {
Log.d(TAG, "UpdatPath for DataAdapter start");
if (mDataAdapter == null) {
// SPRD: If mAdapter is null Init StorageUtil update that here
mNeedUpdatPath = true;
Log.d(TAG, "mDataAdapter is Null");
return;
}
// SPRD: bug 259613
mDataAdapter.UpdataAdapter();
updateDataAdapter(false);
}
public void updateThumbail() {
Log.v(TAG, "updateThumbail start");
mMainHandler.sendEmptyMessage(UPDATE_THUMBAIL);
}
// SPRD :updata DataAdapter and Thum when module switch end @}
// @{ SPRD: bug 258455 begin
public void setModuleVisble(int visibility) {
Log.v(TAG, "setModuleVisble visibility=" + visibility);
if (mFilmStripView != null) {
mFilmStripView.setTextViewVisibility(visibility);
}
} // SPRD: bug 258455 end
// ******************************************************************************
// new feature for auto capture
private boolean mAutoCapture = false;
private static final String KEY_AUTO = "auto";
protected void checkIntent(Intent intent) {
String action = intent.getAction();
if (action == null) {
return;
}
// test
// intent.putExtra(KEY_AUTO, KEY_AUTO);
if (action.equals(MediaStore.ACTION_IMAGE_CAPTURE)
|| action.equals(MediaStore.ACTION_VIDEO_CAPTURE)) {
if (intent.hasExtra(KEY_AUTO)) {
mAutoCapture = KEY_AUTO.equals(intent.getStringExtra(KEY_AUTO));
}
}
}
public boolean isAutoCapture() {
return mAutoCapture;
}
// fixed bug 264715 start add method to judge audio record is busying.
protected boolean proxyIsAudioRecording() {
boolean result = false;
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
// result = audioManager.isAudioRecording();
return result;
}
// fixed bug 264715 end
/* SPRD: added 20140107 of 263964 enabled item not enable sometimes @{ */
public void updateSettingsMutex() {
mCurrentModule.updateSettingsMutex();
}
/* @} */
/* SPRD: fixbug263198 add VideoCall check @{ */
public boolean checkTelephoneVideoCall() {
boolean result = false;
TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
// result = manager.isVTCall();
return result;
}
/* SPRD: fixbug263198 end }@ */
public boolean isImageCaptureIntent() {
return isCaptureIntent();
}
// SPRD: AOB, check current is camera preview state in the method
protected boolean proxyIsCameraPreview() {
if (mFilmStripView != null) {
return mFilmStripView.isCameraPreview();
}
return false;
}
// SPRD: *UI.java use this method
public void setScrollFilmView(ModuleSwitcherView v) {
mFilmStripView.setModuleSwitcherView(v);
}
public void onVideoCaptureShutterButtonClick(View v) {
mCurrentModule.onVideoCaptureShutterButtonClick();
}
private void firstTimeUpdateThumbnail() {
if (!mSecureCamera) {
new LoadCacheThumbnailTask()
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
private class LoadCacheThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
@Override
protected Bitmap doInBackground(Void... params) {
String path = null;
if (mDataAdapter == null) {
return null;
}
if (mCurrentModuleIndex == ModuleSwitcher.VIDEO_MODULE_INDEX) {
path = mDataAdapter.getLastVideoPath();
return getLastVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
} else {
path = mDataAdapter.getImageLastPath();
return getLastImageThumbnail(path);
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
mCurrentModule.updateThumbnail(bitmap);
}
}
private Bitmap getLastImageThumbnail(String imagePath) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = SAMPLE_FACTOR;
return BitmapFactory.decodeFile(imagePath, options);
}
private Bitmap getLastVideoThumbnail(String videoPath, int kind) {
return ThumbnailUtils.createVideoThumbnail(videoPath, kind);
}
private void initLastThumbnailPath() {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
String imagepath = prefs.getString(LAST_IMAGE_PATH, "");
String videopath = prefs.getString(LAST_VIDEO_PATH, "");
if (mDataAdapter != null) {
mDataAdapter.setLastThumbnailPath(imagepath, videopath);
}
}
private void saveLastThumbnailPath() {
String imagepath = null;
String videopath = null;
if (mDataAdapter != null) {
imagepath = mDataAdapter.getImageLastPath();
videopath = mDataAdapter.getLastVideoPath();
}
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
Editor editor = prefs.edit();
editor.putString(LAST_IMAGE_PATH, imagepath);
editor.putString(LAST_VIDEO_PATH, videopath);
editor.commit();
}
}