Revert "Initial checkin of AOSP Messaging app."
This reverts commit 461a34b466.
Change-Id: Iac4ca77eeaa94989e91dead49a7959c905bd3078
This commit is contained in:
@@ -1,481 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.ui.mediapicker;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.Camera;
|
||||
import android.net.Uri;
|
||||
import android.os.SystemClock;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.widget.Chronometer;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.data.MediaPickerMessagePartData;
|
||||
import com.android.messaging.ui.mediapicker.CameraManager.MediaCallback;
|
||||
import com.android.messaging.ui.mediapicker.camerafocus.RenderOverlay;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.OsUtil;
|
||||
import com.android.messaging.util.UiUtils;
|
||||
|
||||
/**
|
||||
* Chooser which allows the user to take pictures or video without leaving the current app/activity
|
||||
*/
|
||||
class CameraMediaChooser extends MediaChooser implements
|
||||
CameraManager.CameraManagerListener {
|
||||
private CameraPreview.CameraPreviewHost mCameraPreviewHost;
|
||||
private ImageButton mFullScreenButton;
|
||||
private ImageButton mSwapCameraButton;
|
||||
private ImageButton mSwapModeButton;
|
||||
private ImageButton mCaptureButton;
|
||||
private ImageButton mCancelVideoButton;
|
||||
private Chronometer mVideoCounter;
|
||||
private boolean mVideoCancelled;
|
||||
private int mErrorToast;
|
||||
private View mEnabledView;
|
||||
private View mMissingPermissionView;
|
||||
|
||||
CameraMediaChooser(final MediaPicker mediaPicker) {
|
||||
super(mediaPicker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSupportedMediaTypes() {
|
||||
if (CameraManager.get().hasAnyCamera()) {
|
||||
return MediaPicker.MEDIA_TYPE_IMAGE | MediaPicker.MEDIA_TYPE_VIDEO;
|
||||
} else {
|
||||
return MediaPicker.MEDIA_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View destroyView() {
|
||||
CameraManager.get().closeCamera();
|
||||
CameraManager.get().setListener(null);
|
||||
CameraManager.get().setSubscriptionDataProvider(null);
|
||||
return super.destroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View createView(final ViewGroup container) {
|
||||
CameraManager.get().setListener(this);
|
||||
CameraManager.get().setSubscriptionDataProvider(this);
|
||||
CameraManager.get().setVideoMode(false);
|
||||
final LayoutInflater inflater = getLayoutInflater();
|
||||
final CameraMediaChooserView view = (CameraMediaChooserView) inflater.inflate(
|
||||
R.layout.mediapicker_camera_chooser,
|
||||
container /* root */,
|
||||
false /* attachToRoot */);
|
||||
mCameraPreviewHost = (CameraPreview.CameraPreviewHost) view.findViewById(
|
||||
R.id.camera_preview);
|
||||
mCameraPreviewHost.getView().setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(final View view, final MotionEvent motionEvent) {
|
||||
if (CameraManager.get().isVideoMode()) {
|
||||
// Prevent the swipe down in video mode because video is always captured in
|
||||
// full screen
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
final View shutterVisual = view.findViewById(R.id.camera_shutter_visual);
|
||||
|
||||
mFullScreenButton = (ImageButton) view.findViewById(R.id.camera_fullScreen_button);
|
||||
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
mMediaPicker.setFullScreen(true);
|
||||
}
|
||||
});
|
||||
|
||||
mSwapCameraButton = (ImageButton) view.findViewById(R.id.camera_swapCamera_button);
|
||||
mSwapCameraButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
CameraManager.get().swapCamera();
|
||||
}
|
||||
});
|
||||
|
||||
mCaptureButton = (ImageButton) view.findViewById(R.id.camera_capture_button);
|
||||
mCaptureButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final float heightPercent = Math.min(mMediaPicker.getViewPager().getHeight() /
|
||||
(float) mCameraPreviewHost.getView().getHeight(), 1);
|
||||
|
||||
if (CameraManager.get().isRecording()) {
|
||||
CameraManager.get().stopVideo();
|
||||
} else {
|
||||
final CameraManager.MediaCallback callback = new CameraManager.MediaCallback() {
|
||||
@Override
|
||||
public void onMediaReady(
|
||||
final Uri uriToVideo, final String contentType,
|
||||
final int width, final int height) {
|
||||
mVideoCounter.stop();
|
||||
if (mVideoCancelled || uriToVideo == null) {
|
||||
mVideoCancelled = false;
|
||||
} else {
|
||||
final Rect startRect = new Rect();
|
||||
// It's possible to throw out the chooser while taking the
|
||||
// picture/video. In that case, still use the attachment, just
|
||||
// skip the startRect
|
||||
if (mView != null) {
|
||||
mView.getGlobalVisibleRect(startRect);
|
||||
}
|
||||
mMediaPicker.dispatchItemsSelected(
|
||||
new MediaPickerMessagePartData(startRect, contentType,
|
||||
uriToVideo, width, height),
|
||||
true /* dismissMediaPicker */);
|
||||
}
|
||||
updateViewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaFailed(final Exception exception) {
|
||||
UiUtils.showToastAtBottom(R.string.camera_media_failure);
|
||||
updateViewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaInfo(final int what) {
|
||||
if (what == MediaCallback.MEDIA_NO_DATA) {
|
||||
UiUtils.showToastAtBottom(R.string.camera_media_failure);
|
||||
}
|
||||
updateViewState();
|
||||
}
|
||||
};
|
||||
if (CameraManager.get().isVideoMode()) {
|
||||
CameraManager.get().startVideo(callback);
|
||||
mVideoCounter.setBase(SystemClock.elapsedRealtime());
|
||||
mVideoCounter.start();
|
||||
updateViewState();
|
||||
} else {
|
||||
showShutterEffect(shutterVisual);
|
||||
CameraManager.get().takePicture(heightPercent, callback);
|
||||
updateViewState();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mSwapModeButton = (ImageButton) view.findViewById(R.id.camera_swap_mode_button);
|
||||
mSwapModeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
final boolean isSwitchingToVideo = !CameraManager.get().isVideoMode();
|
||||
if (isSwitchingToVideo && !OsUtil.hasRecordAudioPermission()) {
|
||||
requestRecordAudioPermission();
|
||||
} else {
|
||||
onSwapMode();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mCancelVideoButton = (ImageButton) view.findViewById(R.id.camera_cancel_button);
|
||||
mCancelVideoButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
mVideoCancelled = true;
|
||||
CameraManager.get().stopVideo();
|
||||
mMediaPicker.dismiss(true);
|
||||
}
|
||||
});
|
||||
|
||||
mVideoCounter = (Chronometer) view.findViewById(R.id.camera_video_counter);
|
||||
|
||||
CameraManager.get().setRenderOverlay((RenderOverlay) view.findViewById(R.id.focus_visual));
|
||||
|
||||
mEnabledView = view.findViewById(R.id.mediapicker_enabled);
|
||||
mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
|
||||
|
||||
// Must set mView before calling updateViewState because it operates on mView
|
||||
mView = view;
|
||||
updateViewState();
|
||||
updateForPermissionState(CameraManager.hasCameraPermission());
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconResource() {
|
||||
return R.drawable.ic_camera_light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconDescriptionResource() {
|
||||
return R.string.mediapicker_cameraChooserDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the view when entering or leaving full-screen camera mode
|
||||
* @param fullScreen
|
||||
*/
|
||||
@Override
|
||||
void onFullScreenChanged(final boolean fullScreen) {
|
||||
super.onFullScreenChanged(fullScreen);
|
||||
if (!fullScreen && CameraManager.get().isVideoMode()) {
|
||||
CameraManager.get().setVideoMode(false);
|
||||
}
|
||||
updateViewState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the control to a default state when it is opened / closed
|
||||
* @param open True if the control is opened
|
||||
*/
|
||||
@Override
|
||||
void onOpenedChanged(final boolean open) {
|
||||
super.onOpenedChanged(open);
|
||||
updateViewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setSelected(final boolean selected) {
|
||||
super.setSelected(selected);
|
||||
if (selected) {
|
||||
if (CameraManager.hasCameraPermission()) {
|
||||
// If an error occurred before the chooser was selected, show it now
|
||||
showErrorToastIfNeeded();
|
||||
} else {
|
||||
requestCameraPermission();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
mMediaPicker.requestPermissions(new String[] { Manifest.permission.CAMERA },
|
||||
MediaPicker.CAMERA_PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
|
||||
private void requestRecordAudioPermission() {
|
||||
mMediaPicker.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO },
|
||||
MediaPicker.RECORD_AUDIO_PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRequestPermissionsResult(
|
||||
final int requestCode, final String permissions[], final int[] grantResults) {
|
||||
if (requestCode == MediaPicker.CAMERA_PERMISSION_REQUEST_CODE) {
|
||||
final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
||||
updateForPermissionState(permissionGranted);
|
||||
if (permissionGranted) {
|
||||
mCameraPreviewHost.onCameraPermissionGranted();
|
||||
}
|
||||
} else if (requestCode == MediaPicker.RECORD_AUDIO_PERMISSION_REQUEST_CODE) {
|
||||
Assert.isFalse(CameraManager.get().isVideoMode());
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// Switch to video mode
|
||||
onSwapMode();
|
||||
} else {
|
||||
// Stay in still-photo mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateForPermissionState(final boolean granted) {
|
||||
// onRequestPermissionsResult can sometimes get called before createView().
|
||||
if (mEnabledView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mEnabledView.setVisibility(granted ? View.VISIBLE : View.GONE);
|
||||
mMissingPermissionView.setVisibility(granted ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSwipeDown() {
|
||||
if (CameraManager.get().isVideoMode()) {
|
||||
return true;
|
||||
}
|
||||
return super.canSwipeDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an error from the camera manager by showing the appropriate error message to the user
|
||||
* @param errorCode One of the CameraManager.ERROR_* constants
|
||||
* @param e The exception which caused the error, if any
|
||||
*/
|
||||
@Override
|
||||
public void onCameraError(final int errorCode, final Exception e) {
|
||||
switch (errorCode) {
|
||||
case CameraManager.ERROR_OPENING_CAMERA:
|
||||
case CameraManager.ERROR_SHOWING_PREVIEW:
|
||||
mErrorToast = R.string.camera_error_opening;
|
||||
break;
|
||||
case CameraManager.ERROR_INITIALIZING_VIDEO:
|
||||
mErrorToast = R.string.camera_error_video_init_fail;
|
||||
updateViewState();
|
||||
break;
|
||||
case CameraManager.ERROR_STORAGE_FAILURE:
|
||||
mErrorToast = R.string.camera_error_storage_fail;
|
||||
updateViewState();
|
||||
break;
|
||||
case CameraManager.ERROR_TAKING_PICTURE:
|
||||
mErrorToast = R.string.camera_error_failure_taking_picture;
|
||||
break;
|
||||
default:
|
||||
mErrorToast = R.string.camera_error_unknown;
|
||||
LogUtil.w(LogUtil.BUGLE_TAG, "Unknown camera error:" + errorCode);
|
||||
break;
|
||||
}
|
||||
showErrorToastIfNeeded();
|
||||
}
|
||||
|
||||
private void showErrorToastIfNeeded() {
|
||||
if (mErrorToast != 0 && mSelected) {
|
||||
UiUtils.showToastAtBottom(mErrorToast);
|
||||
mErrorToast = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraChanged() {
|
||||
updateViewState();
|
||||
}
|
||||
|
||||
private void onSwapMode() {
|
||||
CameraManager.get().setVideoMode(!CameraManager.get().isVideoMode());
|
||||
if (CameraManager.get().isVideoMode()) {
|
||||
mMediaPicker.setFullScreen(true);
|
||||
|
||||
// For now we start recording immediately
|
||||
mCaptureButton.performClick();
|
||||
}
|
||||
updateViewState();
|
||||
}
|
||||
|
||||
private void showShutterEffect(final View shutterVisual) {
|
||||
final float maxAlpha = getContext().getResources().getFraction(
|
||||
R.fraction.camera_shutter_max_alpha, 1 /* base */, 1 /* pBase */);
|
||||
|
||||
// Divide by 2 so each half of the animation adds up to the full duration
|
||||
final int animationDuration = getContext().getResources().getInteger(
|
||||
R.integer.camera_shutter_duration) / 2;
|
||||
|
||||
final AnimationSet animation = new AnimationSet(false /* shareInterpolator */);
|
||||
final Animation alphaInAnimation = new AlphaAnimation(0.0f, maxAlpha);
|
||||
alphaInAnimation.setDuration(animationDuration);
|
||||
animation.addAnimation(alphaInAnimation);
|
||||
|
||||
final Animation alphaOutAnimation = new AlphaAnimation(maxAlpha, 0.0f);
|
||||
alphaOutAnimation.setStartOffset(animationDuration);
|
||||
alphaOutAnimation.setDuration(animationDuration);
|
||||
animation.addAnimation(alphaOutAnimation);
|
||||
|
||||
animation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(final Animation animation) {
|
||||
shutterVisual.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(final Animation animation) {
|
||||
shutterVisual.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(final Animation animation) {
|
||||
}
|
||||
});
|
||||
shutterVisual.startAnimation(animation);
|
||||
}
|
||||
|
||||
/** Updates the state of the buttons and overlays based on the current state of the view */
|
||||
private void updateViewState() {
|
||||
if (mView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Context context = getContext();
|
||||
if (context == null) {
|
||||
// Context is null if the fragment was already removed from the activity
|
||||
return;
|
||||
}
|
||||
final boolean fullScreen = mMediaPicker.isFullScreen();
|
||||
final boolean videoMode = CameraManager.get().isVideoMode();
|
||||
final boolean isRecording = CameraManager.get().isRecording();
|
||||
final boolean isCameraAvailable = isCameraAvailable();
|
||||
final Camera.CameraInfo cameraInfo = CameraManager.get().getCameraInfo();
|
||||
final boolean frontCamera = cameraInfo != null && cameraInfo.facing ==
|
||||
Camera.CameraInfo.CAMERA_FACING_FRONT;
|
||||
|
||||
mView.setSystemUiVisibility(
|
||||
fullScreen ? View.SYSTEM_UI_FLAG_LOW_PROFILE :
|
||||
View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
|
||||
mFullScreenButton.setVisibility(!fullScreen ? View.VISIBLE : View.GONE);
|
||||
mFullScreenButton.setEnabled(isCameraAvailable);
|
||||
mSwapCameraButton.setVisibility(
|
||||
fullScreen && !isRecording && CameraManager.get().hasFrontAndBackCamera() ?
|
||||
View.VISIBLE : View.GONE);
|
||||
mSwapCameraButton.setImageResource(frontCamera ?
|
||||
R.drawable.ic_camera_front_light :
|
||||
R.drawable.ic_camera_rear_light);
|
||||
mSwapCameraButton.setEnabled(isCameraAvailable);
|
||||
|
||||
mCancelVideoButton.setVisibility(isRecording ? View.VISIBLE : View.GONE);
|
||||
mVideoCounter.setVisibility(isRecording ? View.VISIBLE : View.GONE);
|
||||
|
||||
mSwapModeButton.setImageResource(videoMode ?
|
||||
R.drawable.ic_mp_camera_small_light :
|
||||
R.drawable.ic_mp_video_small_light);
|
||||
mSwapModeButton.setContentDescription(context.getString(videoMode ?
|
||||
R.string.camera_switch_to_still_mode : R.string.camera_switch_to_video_mode));
|
||||
mSwapModeButton.setVisibility(isRecording ? View.GONE : View.VISIBLE);
|
||||
mSwapModeButton.setEnabled(isCameraAvailable);
|
||||
|
||||
if (isRecording) {
|
||||
mCaptureButton.setImageResource(R.drawable.ic_mp_capture_stop_large_light);
|
||||
mCaptureButton.setContentDescription(context.getString(
|
||||
R.string.camera_stop_recording));
|
||||
} else if (videoMode) {
|
||||
mCaptureButton.setImageResource(R.drawable.ic_mp_video_large_light);
|
||||
mCaptureButton.setContentDescription(context.getString(
|
||||
R.string.camera_start_recording));
|
||||
} else {
|
||||
mCaptureButton.setImageResource(R.drawable.ic_checkmark_large_light);
|
||||
mCaptureButton.setContentDescription(context.getString(
|
||||
R.string.camera_take_picture));
|
||||
}
|
||||
mCaptureButton.setEnabled(isCameraAvailable);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getActionBarTitleResId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the camera is currently ready camera is loaded and not taking a picture.
|
||||
* otherwise we should avoid taking another picture, swapping camera or recording video.
|
||||
*/
|
||||
private boolean isCameraAvailable() {
|
||||
return CameraManager.get().isCameraAvailable();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user