package com.afollestad.materialcamera.internal; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.graphics.Color; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TextView; import com.afollestad.materialcamera.MaterialCamera; import com.afollestad.materialcamera.R; import com.afollestad.materialcamera.util.CameraUtil; import com.afollestad.materialcamera.util.Degrees; import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import java.io.File; import static android.app.Activity.RESULT_CANCELED; import static com.afollestad.materialcamera.internal.BaseCaptureActivity.CAMERA_POSITION_BACK; import static com.afollestad.materialcamera.internal.BaseCaptureActivity.FLASH_MODE_ALWAYS_ON; import static com.afollestad.materialcamera.internal.BaseCaptureActivity.FLASH_MODE_AUTO; import static com.afollestad.materialcamera.internal.BaseCaptureActivity.FLASH_MODE_OFF; /** * @author Aidan Follestad (afollestad) */ abstract class BaseCameraFragment extends Fragment implements CameraUriInterface, View.OnClickListener { protected TextView mButtonVideo; protected ImageButton mButtonStillshot; protected ImageView mButtonFacing; // protected ImageButton mButtonFlash; // protected TextView mRecordDuration; protected TextView mDelayStartCountdown; private boolean mIsRecording; protected String mOutputUri; protected BaseCaptureInterface mInterface; protected Handler mPositionHandler; protected MediaRecorder mMediaRecorder; protected ImageView cancel_video; protected ImageView save_video; private boolean canRecord=true; protected static void LOG(Object context, String message) { Log.d(context instanceof Class<?> ? ((Class<?>) context).getSimpleName() : context.getClass().getSimpleName(), message); } private final Runnable mPositionUpdater = new Runnable() { @Override public void run() { if (mInterface == null // || mRecordDuration == null ) return; final long mRecordStart = mInterface.getRecordingStart(); final long mRecordEnd = mInterface.getRecordingEnd(); if (mRecordStart == -1 && mRecordEnd == -1) return; final long now = System.currentTimeMillis(); if (mRecordEnd != -1) { if (now >= mRecordEnd) { stopRecordingVideo(true); } else { final long diff = mRecordEnd - now; if (diff<60000) { // mRecordDuration.setText(String.format("-%s", CameraUtil.getDurationString(diff))); mButtonVideo.setText(String.format("-%s", CameraUtil.getDurationString(diff))); }else { stopRecordingVideo(false); mIsRecording = false; } } } else { // mRecordDuration.setText(CameraUtil.getDurationString(now - mRecordStart)); if (now-mRecordStart<60000) { mButtonVideo.setText(CameraUtil.getDurationString(now - mRecordStart)); }else { stopRecordingVideo(false); mIsRecording = false; } } if (mPositionHandler != null) mPositionHandler.postDelayed(this, 1000); } }; @Override public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.mcam_fragment_videocapture, container, false); } protected void setImageRes(ImageView iv, @DrawableRes int res) { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && iv.getBackground() instanceof RippleDrawable) { // RippleDrawable rd = (RippleDrawable) iv.getBackground(); // rd.setColor(ColorStateList.valueOf(CameraUtil.adjustAlpha(mIconTextColor, 0.3f))); // } // Drawable d = AppCompatResources.getDrawable(iv.getContext(), res); // d = DrawableCompat.wrap(d.mutate()); // DrawableCompat.setTint(d, mIconTextColor); // iv.setImageDrawable(d); } protected void setImageRes(TextView iv, @DrawableRes int res) { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && iv.getBackground() instanceof RippleDrawable) { // RippleDrawable rd = (RippleDrawable) iv.getBackground(); // rd.setColor(ColorStateList.valueOf(CameraUtil.adjustAlpha(mIconTextColor, 0.3f))); // } // Drawable d = AppCompatResources.getDrawable(iv.getContext(), res); // d = DrawableCompat.wrap(d.mutate()); // DrawableCompat.setTint(d, mIconTextColor); // iv.setBackground(d); } @SuppressLint("SetTextI18n") @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mDelayStartCountdown = (TextView) view.findViewById(R.id.delayStartCountdown); mButtonVideo = (TextView) view.findViewById(R.id.video); mButtonStillshot = (ImageButton) view.findViewById(R.id.stillshot); // mRecordDuration = (TextView) view.findViewById(R.id.recordDuration); mButtonFacing = (ImageView) view.findViewById(R.id.facing); ImageView back = (ImageView) view.findViewById(R.id.back); save_video= (ImageView) view.findViewById(R.id.save); cancel_video= (ImageView) view.findViewById(R.id.delete); if (mInterface.shouldHideCameraFacing() || CameraUtil.isChromium()) { mButtonFacing.setVisibility(View.GONE); } else { setImageRes(mButtonFacing, mInterface.getCurrentCameraPosition() == CAMERA_POSITION_BACK ? mInterface.iconFrontCamera() : mInterface.iconRearCamera()); } // mButtonFlash = (ImageButton) view.findViewById(R.id.flash); setupFlashMode(); mButtonVideo.setOnClickListener(this); mButtonStillshot.setOnClickListener(this); mButtonFacing.setOnClickListener(this); back.setOnClickListener(this); cancel_video.setOnClickListener(this); save_video.setOnClickListener(this); // mButtonFlash.setOnClickListener(this); // int primaryColor = getArguments().getInt(CameraIntentKey.PRIMARY_COLOR); // view.findViewById(R.id.controlsFrame).setBackgroundColor(primaryColor); // mRecordDuration.setTextColor(mIconTextColor); if (mMediaRecorder != null && mIsRecording) { setImageRes(mButtonVideo, mInterface.iconStop()); } else { setImageRes(mButtonVideo, mInterface.iconRecord()); mInterface.setDidRecord(false); } if (savedInstanceState != null) mOutputUri = savedInstanceState.getString("output_uri"); if (mInterface.useStillshot()) { mButtonVideo.setVisibility(View.GONE); // mRecordDuration.setVisibility(View.GONE); mButtonStillshot.setVisibility(View.VISIBLE); setImageRes(mButtonStillshot, mInterface.iconStillshot()); // mButtonFlash.setVisibility(View.VISIBLE); } if (mInterface.autoRecordDelay() < 1000) { mDelayStartCountdown.setVisibility(View.GONE); } else { mDelayStartCountdown.setText(Long.toString(mInterface.autoRecordDelay() / 1000)); } } protected void onFlashModesLoaded() { if (getCurrentCameraPosition() != BaseCaptureActivity.CAMERA_POSITION_FRONT) { invalidateFlash(false); } } private boolean mDidAutoRecord = false; private Handler mDelayHandler; private int mDelayCurrentSecond = -1; protected void onCameraOpened() { if (mDidAutoRecord || mInterface == null || mInterface.useStillshot() || mInterface.autoRecordDelay() < 0 || getActivity() == null) { mDelayStartCountdown.setVisibility(View.GONE); mDelayHandler = null; return; } mDidAutoRecord = true; mButtonFacing.setVisibility(View.GONE); if (mInterface.autoRecordDelay() == 0) { mDelayStartCountdown.setVisibility(View.GONE); mIsRecording = startRecordingVideo(); mDelayHandler = null; return; } mDelayHandler = new Handler(); mButtonVideo.setEnabled(false); if (mInterface.autoRecordDelay() < 1000) { // Less than a second delay mDelayStartCountdown.setVisibility(View.GONE); mDelayHandler.postDelayed(new Runnable() { @Override public void run() { if (!isAdded() || getActivity() == null || mIsRecording) return; mButtonVideo.setEnabled(true); mIsRecording = startRecordingVideo(); mDelayHandler = null; } }, mInterface.autoRecordDelay()); return; } mDelayStartCountdown.setVisibility(View.VISIBLE); mDelayCurrentSecond = (int) mInterface.autoRecordDelay() / 1000; mDelayHandler.postDelayed(new Runnable() { @SuppressLint("SetTextI18n") @Override public void run() { if (!isAdded() || getActivity() == null || mIsRecording) return; mDelayCurrentSecond -= 1; mDelayStartCountdown.setText(Integer.toString(mDelayCurrentSecond)); if (mDelayCurrentSecond == 0) { mDelayStartCountdown.setVisibility(View.GONE); mButtonVideo.setEnabled(true); mIsRecording = startRecordingVideo(); mDelayHandler = null; return; } mDelayHandler.postDelayed(this, 1000); } }, 1000); } @Override public void onDestroyView() { super.onDestroyView(); mButtonVideo = null; mButtonStillshot = null; mButtonFacing = null; } @Override public void onResume() { super.onResume(); if (mInterface != null && mInterface.hasLengthLimit()) { if (mInterface.countdownImmediately() || mInterface.getRecordingStart() > -1) { if (mInterface.getRecordingStart() == -1) mInterface.setRecordingStart(System.currentTimeMillis()); startCounter(); } else { if (mInterface.getLengthLimit()<60000) { mButtonVideo.setText(String.format("-%s", CameraUtil.getDurationString(mInterface.getLengthLimit()))); }else { stopRecordingVideo(false); mIsRecording = false; } // mRecordDuration.setText(String.format("-%s", CameraUtil.getDurationString(mInterface.getLengthLimit()))); } } } @SuppressWarnings("deprecation") @Override public final void onAttach(Activity activity) { super.onAttach(activity); mInterface = (BaseCaptureInterface) activity; } @NonNull protected final File getOutputMediaFile() { return CameraUtil.makeTempFile(getActivity(), null, "VID_", ".mp4"); } @NonNull protected final File getOutputPictureFile() { return CameraUtil.makeTempFile(getActivity(), null, "IMG_", ".jpg"); } public abstract void openCamera(); public abstract void closeCamera(); public void cleanup() { closeCamera(); releaseRecorder(); stopCounter(); } public abstract void takeStillshot(); public abstract void onPreferencesUpdated(); @Override public void onPause() { super.onPause(); cleanup(); } @Override public final void onDetach() { super.onDetach(); mInterface = null; } public final void startCounter() { if (mPositionHandler == null) mPositionHandler = new Handler(); else mPositionHandler.removeCallbacks(mPositionUpdater); mPositionHandler.post(mPositionUpdater); } @BaseCaptureActivity.CameraPosition public final int getCurrentCameraPosition() { if (mInterface == null) return BaseCaptureActivity.CAMERA_POSITION_UNKNOWN; return mInterface.getCurrentCameraPosition(); } public final int getCurrentCameraId() { if (mInterface.getCurrentCameraPosition() == BaseCaptureActivity.CAMERA_POSITION_BACK) return (Integer) mInterface.getBackCamera(); else return (Integer) mInterface.getFrontCamera(); } public final void stopCounter() { if (mPositionHandler != null) { mPositionHandler.removeCallbacks(mPositionUpdater); mPositionHandler = null; } } public final void releaseRecorder() { if (mMediaRecorder != null) { if (mIsRecording) { try { mMediaRecorder.stop(); } catch (Throwable t) { //noinspection ResultOfMethodCallIgnored new File(mOutputUri).delete(); t.printStackTrace(); } mIsRecording = false; } mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder = null; } } public boolean startRecordingVideo() { mButtonVideo.setTextColor(Color.WHITE); mButtonVideo.setBackgroundResource(R.drawable.record_background); cancel_video.setVisibility(View.GONE); save_video.setVisibility(View.GONE); if (mInterface != null && mInterface.hasLengthLimit() && !mInterface.countdownImmediately()) { // Countdown wasn't started in onResume, start it now if (mInterface.getRecordingStart() == -1) mInterface.setRecordingStart(System.currentTimeMillis()); startCounter(); } final int orientation = Degrees.getActivityOrientation(getActivity()); //noinspection ResourceType getActivity().setRequestedOrientation(orientation); mInterface.setDidRecord(true); return true; } public void stopRecordingVideo(boolean reachedZero) { mButtonVideo.setTextColor(Color.rgb(119,119,119)); mButtonVideo.setBackgroundResource(R.drawable.video_length); mButtonVideo.setPadding(36,18,36,18); cancel_video.setVisibility(View.VISIBLE); save_video.setVisibility(View.VISIBLE); canRecord=false; // getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } @Override public final void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("output_uri", mOutputUri); } @Override public final String getOutputUri() { return mOutputUri; } protected final void throwError(Exception e) { Activity act = getActivity(); if (act != null) { act.setResult(RESULT_CANCELED, new Intent().putExtra(MaterialCamera.ERROR_EXTRA, e)); act.finish(); } } @Override public void onClick(View view) { final int id = view.getId(); if (id == R.id.facing) { canRecord=true; if (cancel_video.isShown()&&save_video.isShown()){ new MaterialDialog.Builder(getActivity()) .title("提示") .content("您已经录制了视频确定放弃吗?") .positiveText("确定") .negativeText("取消") .onPositive(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { save_video.setVisibility(View.GONE); cancel_video.setVisibility(View.GONE); mButtonVideo.setBackgroundResource(R.drawable.background); mButtonVideo.setText(""); mInterface.toggleCameraPosition(); setImageRes(mButtonFacing, mInterface.getCurrentCameraPosition() == BaseCaptureActivity.CAMERA_POSITION_BACK ? mInterface.iconFrontCamera() : mInterface.iconRearCamera()); closeCamera(); openCamera(); setupFlashMode(); } }) .onNegative(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { mButtonVideo.setEnabled(false); } }) .show(); }else { mButtonVideo.setBackgroundResource(R.drawable.start_record); mButtonVideo.setText(""); mInterface.toggleCameraPosition(); setImageRes(mButtonFacing, mInterface.getCurrentCameraPosition() == BaseCaptureActivity.CAMERA_POSITION_BACK ? mInterface.iconFrontCamera() : mInterface.iconRearCamera()); closeCamera(); openCamera(); setupFlashMode(); } } else if (id == R.id.video) { if (mIsRecording) { stopRecordingVideo(false); mIsRecording = false; } else { if (canRecord) { mIsRecording = startRecordingVideo(); } } } else if (id == R.id.stillshot) { takeStillshot(); }else if (id==R.id.back){ getActivity().finish(); }else if (id==R.id.save){ showPreView(); }else if (id==R.id.delete){ new MaterialDialog.Builder(getActivity()) .title("提示") .content("要放弃当前拍摄的视频吗?") .positiveText("确认") .negativeText("取消") .onPositive(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { //重新拍摄 mInterface.onRetry(getOutputUri()); } }) .show(); } } public void showPreView() { } private void invalidateFlash(boolean toggle) { if (toggle) mInterface.toggleFlashMode(); setupFlashMode(); onPreferencesUpdated(); } private void setupFlashMode() { // if (mInterface.shouldHideFlash()) { // mButtonFlash.setVisibility(View.GONE); // return; // } else { // mButtonFlash.setVisibility(View.VISIBLE); // } final int res; switch (mInterface.getFlashMode()) { case FLASH_MODE_AUTO: res = mInterface.iconFlashAuto(); break; case FLASH_MODE_ALWAYS_ON: res = mInterface.iconFlashOn(); break; case FLASH_MODE_OFF: default: res = mInterface.iconFlashOff(); } // setImageRes(mButtonFlash, res); } }