mirror of
https://github.com/SimpleMobileTools/Simple-Camera.git
synced 2025-02-19 21:01:01 +01:00
convert MainActivity to kotlin
This commit is contained in:
parent
c50608aa27
commit
900f12634e
@ -7,6 +7,7 @@ import android.util.Log
|
|||||||
import com.simplemobiletools.camera.activities.MainActivity
|
import com.simplemobiletools.camera.activities.MainActivity
|
||||||
import com.simplemobiletools.filepicker.extensions.getFileDocument
|
import com.simplemobiletools.filepicker.extensions.getFileDocument
|
||||||
import com.simplemobiletools.filepicker.extensions.needsStupidWritePermissions
|
import com.simplemobiletools.filepicker.extensions.needsStupidWritePermissions
|
||||||
|
import com.simplemobiletools.filepicker.extensions.toast
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class PhotoProcessor(val activity: MainActivity, val uri: Uri?) : AsyncTask<Byte
|
|||||||
val config = Config.newInstance(activity)
|
val config = Config.newInstance(activity)
|
||||||
if (config.treeUri.isEmpty()) {
|
if (config.treeUri.isEmpty()) {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
Utils.showToast(activity, R.string.save_error_internal_storage)
|
activity.toast(R.string.save_error_internal_storage)
|
||||||
}
|
}
|
||||||
config.savePhotosFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
|
config.savePhotosFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
|
||||||
return ""
|
return ""
|
||||||
|
@ -9,7 +9,6 @@ import android.graphics.Point
|
|||||||
import android.hardware.Camera
|
import android.hardware.Camera
|
||||||
import android.support.v4.content.ContextCompat
|
import android.support.v4.content.ContextCompat
|
||||||
import com.simplemobiletools.filepicker.extensions.getFileDocument
|
import com.simplemobiletools.filepicker.extensions.getFileDocument
|
||||||
import com.simplemobiletools.filepicker.extensions.hasStoragePermission
|
|
||||||
import com.simplemobiletools.filepicker.extensions.needsStupidWritePermissions
|
import com.simplemobiletools.filepicker.extensions.needsStupidWritePermissions
|
||||||
import com.simplemobiletools.filepicker.extensions.toast
|
import com.simplemobiletools.filepicker.extensions.toast
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -102,8 +101,6 @@ class Utils {
|
|||||||
|
|
||||||
fun hasCameraPermission(context: Context) = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
|
fun hasCameraPermission(context: Context) = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
|
||||||
|
|
||||||
fun hasStoragePermission(context: Context) = context.hasStoragePermission()
|
|
||||||
|
|
||||||
fun hasAudioPermission(cxt: Context) = ContextCompat.checkSelfPermission(cxt, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
|
fun hasAudioPermission(cxt: Context) = ContextCompat.checkSelfPermission(cxt, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
|
||||||
|
|
||||||
fun needsStupidWritePermissions(context: Context, path: String) = context.needsStupidWritePermissions(path)
|
fun needsStupidWritePermissions(context: Context, path: String) = context.needsStupidWritePermissions(path)
|
||||||
|
@ -1,711 +0,0 @@
|
|||||||
package com.simplemobiletools.camera.activities;
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.hardware.Camera;
|
|
||||||
import android.hardware.Sensor;
|
|
||||||
import android.hardware.SensorEvent;
|
|
||||||
import android.hardware.SensorEventListener;
|
|
||||||
import android.hardware.SensorManager;
|
|
||||||
import android.media.MediaScannerConnection;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.provider.MediaStore;
|
|
||||||
import android.support.v4.app.ActivityCompat;
|
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.SurfaceView;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.simplemobiletools.camera.Config;
|
|
||||||
import com.simplemobiletools.camera.Constants;
|
|
||||||
import com.simplemobiletools.camera.views.FocusRectView;
|
|
||||||
import com.simplemobiletools.camera.PhotoProcessor;
|
|
||||||
import com.simplemobiletools.camera.Preview;
|
|
||||||
import com.simplemobiletools.camera.Preview.PreviewListener;
|
|
||||||
import com.simplemobiletools.camera.R;
|
|
||||||
import com.simplemobiletools.camera.Utils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.OnClick;
|
|
||||||
|
|
||||||
public class MainActivity extends SimpleActivity
|
|
||||||
implements SensorEventListener, PreviewListener, PhotoProcessor.MediaSavedListener, MediaScannerConnection.OnScanCompletedListener {
|
|
||||||
@BindView(R.id.view_holder) RelativeLayout mViewHolder;
|
|
||||||
@BindView(R.id.toggle_camera) ImageView mToggleCameraBtn;
|
|
||||||
@BindView(R.id.toggle_flash) ImageView mToggleFlashBtn;
|
|
||||||
@BindView(R.id.toggle_photo_video) ImageView mTogglePhotoVideoBtn;
|
|
||||||
@BindView(R.id.shutter) ImageView mShutterBtn;
|
|
||||||
@BindView(R.id.video_rec_curr_timer) TextView mRecCurrTimer;
|
|
||||||
@BindView(R.id.settings) View mSettingsBtn;
|
|
||||||
@BindView(R.id.last_photo_video_preview) ImageView mLastPhotoVideoPreview;
|
|
||||||
|
|
||||||
private static final int CAMERA_STORAGE_PERMISSION = 1;
|
|
||||||
private static final int AUDIO_PERMISSION = 2;
|
|
||||||
private static final int FADE_DELAY = 5000;
|
|
||||||
|
|
||||||
private static SensorManager mSensorManager;
|
|
||||||
private static Preview mPreview;
|
|
||||||
private static FocusRectView mFocusRectView;
|
|
||||||
private static Handler mTimerHandler;
|
|
||||||
private static Uri mPreviewUri;
|
|
||||||
private static Handler mFadeHandler;
|
|
||||||
|
|
||||||
private static boolean mIsFlashEnabled;
|
|
||||||
private static boolean mIsInPhotoMode;
|
|
||||||
private static boolean mIsAskingPermissions;
|
|
||||||
private static boolean mIsCameraAvailable;
|
|
||||||
private static boolean mIsImageCaptureIntent;
|
|
||||||
private static boolean mIsVideoCaptureIntent;
|
|
||||||
private static boolean mIsHardwareShutterHandled;
|
|
||||||
private static int mCurrVideoRecTimer;
|
|
||||||
private static int mOrientation;
|
|
||||||
private static int mCurrCamera;
|
|
||||||
private static int mLastHandledOrientation;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
||||||
tryInitCamera();
|
|
||||||
|
|
||||||
final ActionBar actionbar = getSupportActionBar();
|
|
||||||
if (actionbar != null)
|
|
||||||
actionbar.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
||||||
if (keyCode == KeyEvent.KEYCODE_CAMERA && !mIsHardwareShutterHandled) {
|
|
||||||
mIsHardwareShutterHandled = true;
|
|
||||||
shutterPressed();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.onKeyDown(keyCode, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
|
||||||
if (keyCode == KeyEvent.KEYCODE_CAMERA) {
|
|
||||||
mIsHardwareShutterHandled = false;
|
|
||||||
}
|
|
||||||
return super.onKeyUp(keyCode, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideToggleModeAbout() {
|
|
||||||
if (mTogglePhotoVideoBtn != null)
|
|
||||||
mTogglePhotoVideoBtn.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if (mSettingsBtn != null)
|
|
||||||
mSettingsBtn.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryInitCamera() {
|
|
||||||
if (hasCameraAndStoragePermission()) {
|
|
||||||
initializeCamera();
|
|
||||||
handleIntent();
|
|
||||||
} else {
|
|
||||||
final List<String> permissions = new ArrayList<>(2);
|
|
||||||
if (!Utils.Companion.hasCameraPermission(getApplicationContext())) {
|
|
||||||
permissions.add(Manifest.permission.CAMERA);
|
|
||||||
}
|
|
||||||
if (!Utils.Companion.hasStoragePermission(getApplicationContext())) {
|
|
||||||
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
|
||||||
}
|
|
||||||
ActivityCompat.requestPermissions(this, permissions.toArray(new String[permissions.size()]), CAMERA_STORAGE_PERMISSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleIntent() {
|
|
||||||
final Intent intent = getIntent();
|
|
||||||
if (intent != null && intent.getAction() != null) {
|
|
||||||
if (intent.getExtras() != null && intent.getAction().equals(MediaStore.ACTION_IMAGE_CAPTURE) ||
|
|
||||||
intent.getAction().equals(MediaStore.ACTION_IMAGE_CAPTURE_SECURE)) {
|
|
||||||
mIsImageCaptureIntent = true;
|
|
||||||
hideToggleModeAbout();
|
|
||||||
final Object output = intent.getExtras().get(MediaStore.EXTRA_OUTPUT);
|
|
||||||
if (output != null && output instanceof Uri) {
|
|
||||||
mPreview.setTargetUri((Uri) output);
|
|
||||||
}
|
|
||||||
} else if (intent.getAction().equals(MediaStore.ACTION_VIDEO_CAPTURE)) {
|
|
||||||
mIsVideoCaptureIntent = true;
|
|
||||||
hideToggleModeAbout();
|
|
||||||
mShutterBtn.setImageDrawable(getResources().getDrawable(R.mipmap.video_rec));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeCamera() {
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
ButterKnife.bind(this);
|
|
||||||
|
|
||||||
if (Utils.Companion.hasNavBar(getResources()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
|
||||||
final View btnLayout = findViewById(R.id.btn_holder);
|
|
||||||
final RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) btnLayout.getLayoutParams();
|
|
||||||
lp.setMargins(0, 0, 0, lp.bottomMargin + Utils.Companion.getNavBarHeight(getResources()));
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrCamera = getConfig().getLastUsedCamera();
|
|
||||||
mPreview = new Preview(this, (SurfaceView) findViewById(R.id.camera_view), this);
|
|
||||||
mPreview.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
||||||
mViewHolder.addView(mPreview);
|
|
||||||
mToggleCameraBtn.setImageResource(mCurrCamera == Camera.CameraInfo.CAMERA_FACING_BACK ? R.mipmap.camera_front : R.mipmap.camera_back);
|
|
||||||
|
|
||||||
mFocusRectView = new FocusRectView(getApplicationContext());
|
|
||||||
mViewHolder.addView(mFocusRectView);
|
|
||||||
|
|
||||||
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
|
|
||||||
mIsInPhotoMode = true;
|
|
||||||
mTimerHandler = new Handler();
|
|
||||||
mFadeHandler = new Handler();
|
|
||||||
mIsFlashEnabled = getConfig().getLastFlashlightState();
|
|
||||||
setupPreviewImage(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasCameraAndStoragePermission() {
|
|
||||||
return Utils.Companion.hasCameraPermission(getApplicationContext()) && Utils.Companion.hasStoragePermission(getApplicationContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
mIsAskingPermissions = false;
|
|
||||||
|
|
||||||
if (requestCode == CAMERA_STORAGE_PERMISSION) {
|
|
||||||
if (hasCameraAndStoragePermission()) {
|
|
||||||
initializeCamera();
|
|
||||||
handleIntent();
|
|
||||||
} else {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.no_permissions);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
} else if (requestCode == AUDIO_PERMISSION) {
|
|
||||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
togglePhotoVideo();
|
|
||||||
} else {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.no_audio_permissions);
|
|
||||||
if (mIsVideoCaptureIntent)
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.toggle_camera)
|
|
||||||
public void toggleCamera() {
|
|
||||||
if (!checkCameraAvailable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCurrCamera == Camera.CameraInfo.CAMERA_FACING_BACK) {
|
|
||||||
mCurrCamera = Camera.CameraInfo.CAMERA_FACING_FRONT;
|
|
||||||
} else {
|
|
||||||
mCurrCamera = Camera.CameraInfo.CAMERA_FACING_BACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfig().setLastUsedCamera(mCurrCamera);
|
|
||||||
int newIconId = R.mipmap.camera_front;
|
|
||||||
mPreview.releaseCamera();
|
|
||||||
if (mPreview.setCamera(mCurrCamera)) {
|
|
||||||
if (mCurrCamera == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
|
||||||
newIconId = R.mipmap.camera_back;
|
|
||||||
}
|
|
||||||
mToggleCameraBtn.setImageResource(newIconId);
|
|
||||||
disableFlash();
|
|
||||||
hideTimer();
|
|
||||||
} else {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.camera_switch_error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.last_photo_video_preview)
|
|
||||||
public void showLastMediaPreview() {
|
|
||||||
if (mPreviewUri == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final String REVIEW_ACTION = "com.android.camera.action.REVIEW";
|
|
||||||
Intent intent = new Intent(REVIEW_ACTION, mPreviewUri);
|
|
||||||
this.startActivity(intent);
|
|
||||||
} catch (ActivityNotFoundException e) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, mPreviewUri);
|
|
||||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
|
||||||
startActivity(intent);
|
|
||||||
} else {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.no_gallery_app_available);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.toggle_flash)
|
|
||||||
public void toggleFlash() {
|
|
||||||
if (!checkCameraAvailable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mIsFlashEnabled = !mIsFlashEnabled;
|
|
||||||
checkFlash();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkFlash() {
|
|
||||||
if (mIsFlashEnabled) {
|
|
||||||
enableFlash();
|
|
||||||
} else {
|
|
||||||
disableFlash();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disableFlash() {
|
|
||||||
mPreview.disableFlash();
|
|
||||||
mToggleFlashBtn.setImageResource(R.mipmap.flash_off);
|
|
||||||
mIsFlashEnabled = false;
|
|
||||||
getConfig().setLastFlashlightState(mIsFlashEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableFlash() {
|
|
||||||
mPreview.enableFlash();
|
|
||||||
mToggleFlashBtn.setImageResource(R.mipmap.flash_on);
|
|
||||||
mIsFlashEnabled = true;
|
|
||||||
getConfig().setLastFlashlightState(mIsFlashEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.shutter)
|
|
||||||
public void handleShutterPressed() {
|
|
||||||
shutterPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void shutterPressed() {
|
|
||||||
if (!checkCameraAvailable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleShutter();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleShutter() {
|
|
||||||
if (mIsInPhotoMode) {
|
|
||||||
toggleBottomButtons(true);
|
|
||||||
mPreview.takePicture();
|
|
||||||
new Handler().postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
toggleBottomButtons(false);
|
|
||||||
}
|
|
||||||
}, Preview.PHOTO_PREVIEW_LENGTH);
|
|
||||||
} else {
|
|
||||||
final Resources res = getResources();
|
|
||||||
final boolean isRecording = mPreview.toggleRecording();
|
|
||||||
if (isRecording) {
|
|
||||||
mShutterBtn.setImageDrawable(res.getDrawable(R.mipmap.video_stop));
|
|
||||||
mToggleCameraBtn.setVisibility(View.INVISIBLE);
|
|
||||||
showTimer();
|
|
||||||
} else {
|
|
||||||
mShutterBtn.setImageDrawable(res.getDrawable(R.mipmap.video_rec));
|
|
||||||
mToggleCameraBtn.setVisibility(View.VISIBLE);
|
|
||||||
hideTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleBottomButtons(Boolean hide) {
|
|
||||||
mShutterBtn.animate().alpha(hide ? 0 : 1).start();
|
|
||||||
mToggleCameraBtn.animate().alpha(hide ? 0 : 1).start();
|
|
||||||
mToggleFlashBtn.animate().alpha(hide ? 0 : 1).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.settings)
|
|
||||||
public void launchSettings() {
|
|
||||||
if (mSettingsBtn.getAlpha() == 1.f) {
|
|
||||||
final Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
} else {
|
|
||||||
fadeInButtons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.toggle_photo_video)
|
|
||||||
public void handleTogglePhotoVideo() {
|
|
||||||
togglePhotoVideo();
|
|
||||||
checkButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void togglePhotoVideo() {
|
|
||||||
if (!checkCameraAvailable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Utils.Companion.hasAudioPermission(getApplicationContext())) {
|
|
||||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, AUDIO_PERMISSION);
|
|
||||||
mIsAskingPermissions = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsVideoCaptureIntent)
|
|
||||||
mPreview.trySwitchToVideo();
|
|
||||||
|
|
||||||
disableFlash();
|
|
||||||
hideTimer();
|
|
||||||
mIsInPhotoMode = !mIsInPhotoMode;
|
|
||||||
mToggleCameraBtn.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkButtons() {
|
|
||||||
if (mIsInPhotoMode) {
|
|
||||||
initPhotoButtons();
|
|
||||||
} else {
|
|
||||||
tryInitVideoButtons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initPhotoButtons() {
|
|
||||||
final Resources res = getResources();
|
|
||||||
mTogglePhotoVideoBtn.setImageDrawable(res.getDrawable(R.mipmap.videocam));
|
|
||||||
mShutterBtn.setImageDrawable(res.getDrawable(R.mipmap.camera));
|
|
||||||
mPreview.initPhotoMode();
|
|
||||||
setupPreviewImage(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryInitVideoButtons() {
|
|
||||||
if (mPreview.initRecorder()) {
|
|
||||||
initVideoButtons();
|
|
||||||
} else {
|
|
||||||
if (!mIsVideoCaptureIntent) {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.video_mode_error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initVideoButtons() {
|
|
||||||
final Resources res = getResources();
|
|
||||||
mTogglePhotoVideoBtn.setImageDrawable(res.getDrawable(R.mipmap.photo));
|
|
||||||
mToggleCameraBtn.setVisibility(View.VISIBLE);
|
|
||||||
mShutterBtn.setImageDrawable(res.getDrawable(R.mipmap.video_rec));
|
|
||||||
checkFlash();
|
|
||||||
setupPreviewImage(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupPreviewImage(boolean isPhoto) {
|
|
||||||
final Uri uri = (isPhoto) ? MediaStore.Images.Media.EXTERNAL_CONTENT_URI : MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
|
||||||
final long lastMediaId = getLastMediaId(uri);
|
|
||||||
if (lastMediaId == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final ContentResolver cr = getContentResolver();
|
|
||||||
mPreviewUri = Uri.withAppendedPath(uri, String.valueOf(lastMediaId));
|
|
||||||
Bitmap tmb;
|
|
||||||
|
|
||||||
if (isPhoto) {
|
|
||||||
tmb = MediaStore.Images.Thumbnails.getThumbnail(cr, lastMediaId, MediaStore.Images.Thumbnails.MICRO_KIND, null);
|
|
||||||
final int rotationDegrees = getImageRotation();
|
|
||||||
tmb = rotateThumbnail(tmb, rotationDegrees);
|
|
||||||
} else {
|
|
||||||
tmb = MediaStore.Video.Thumbnails.getThumbnail(cr, lastMediaId, MediaStore.Video.Thumbnails.MICRO_KIND, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPreviewImage(tmb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getImageRotation() {
|
|
||||||
final String[] projection = {MediaStore.Images.ImageColumns.ORIENTATION};
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
final int orientationIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION);
|
|
||||||
return cursor.getInt(orientationIndex);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap rotateThumbnail(Bitmap tmb, int degrees) {
|
|
||||||
if (degrees == 0)
|
|
||||||
return tmb;
|
|
||||||
|
|
||||||
final Matrix matrix = new Matrix();
|
|
||||||
matrix.setRotate(degrees, tmb.getWidth() / 2, tmb.getHeight() / 2);
|
|
||||||
return Bitmap.createBitmap(tmb, 0, 0, tmb.getWidth(), tmb.getHeight(), matrix, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPreviewImage(final Bitmap bmp) {
|
|
||||||
if (bmp != null) {
|
|
||||||
mLastPhotoVideoPreview.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mLastPhotoVideoPreview.setImageBitmap(bmp);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getLastMediaId(Uri uri) {
|
|
||||||
final String[] projection = {MediaStore.Images.ImageColumns._ID};
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
cursor = getContentResolver().query(uri, projection, null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
final int idIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID);
|
|
||||||
return cursor.getLong(idIndex);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleFadeOut() {
|
|
||||||
mFadeHandler.postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
fadeOutButtons();
|
|
||||||
}
|
|
||||||
}, FADE_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fadeOutButtons() {
|
|
||||||
fadeAnim(mSettingsBtn, .5f);
|
|
||||||
fadeAnim(mTogglePhotoVideoBtn, .0f);
|
|
||||||
fadeAnim(mLastPhotoVideoPreview, .0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fadeInButtons() {
|
|
||||||
fadeAnim(mSettingsBtn, 1.f);
|
|
||||||
fadeAnim(mTogglePhotoVideoBtn, 1.f);
|
|
||||||
fadeAnim(mLastPhotoVideoPreview, 1.f);
|
|
||||||
scheduleFadeOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fadeAnim(View view, float value) {
|
|
||||||
view.animate().alpha(value).start();
|
|
||||||
if (value == .0f) {
|
|
||||||
view.setClickable(false);
|
|
||||||
} else {
|
|
||||||
view.setClickable(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideNavigationBarIcons() {
|
|
||||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideTimer() {
|
|
||||||
mRecCurrTimer.setText(Utils.Companion.formatSeconds(0));
|
|
||||||
mRecCurrTimer.setVisibility(View.GONE);
|
|
||||||
mCurrVideoRecTimer = 0;
|
|
||||||
mTimerHandler.removeCallbacksAndMessages(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showTimer() {
|
|
||||||
mRecCurrTimer.setVisibility(View.VISIBLE);
|
|
||||||
setupTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupTimer() {
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mRecCurrTimer.setText(Utils.Companion.formatSeconds(mCurrVideoRecTimer++));
|
|
||||||
mTimerHandler.postDelayed(this, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
if (hasCameraAndStoragePermission()) {
|
|
||||||
resumeCameraItems();
|
|
||||||
setupPreviewImage(mIsInPhotoMode);
|
|
||||||
scheduleFadeOut();
|
|
||||||
|
|
||||||
if (mIsVideoCaptureIntent && mIsInPhotoMode) {
|
|
||||||
togglePhotoVideo();
|
|
||||||
checkButtons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resumeCameraItems() {
|
|
||||||
final int cnt = Camera.getNumberOfCameras();
|
|
||||||
if (cnt == 1) {
|
|
||||||
mToggleCameraBtn.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPreview.setCamera(mCurrCamera)) {
|
|
||||||
hideNavigationBarIcons();
|
|
||||||
checkFlash();
|
|
||||||
|
|
||||||
if (mSensorManager != null) {
|
|
||||||
final Sensor accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
|
||||||
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mIsInPhotoMode) {
|
|
||||||
initVideoButtons();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.camera_switch_error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
||||||
if (!hasCameraAndStoragePermission() || mIsAskingPermissions)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mFadeHandler != null)
|
|
||||||
mFadeHandler.removeCallbacksAndMessages(null);
|
|
||||||
|
|
||||||
hideTimer();
|
|
||||||
if (mPreview != null) {
|
|
||||||
mPreview.releaseCamera();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSensorManager != null)
|
|
||||||
mSensorManager.unregisterListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSensorChanged(SensorEvent event) {
|
|
||||||
if (event.values[0] < 6.5 && event.values[0] > -6.5) {
|
|
||||||
mOrientation = Constants.ORIENT_PORTRAIT;
|
|
||||||
} else {
|
|
||||||
if (event.values[0] > 0) {
|
|
||||||
mOrientation = Constants.ORIENT_LANDSCAPE_LEFT;
|
|
||||||
} else {
|
|
||||||
mOrientation = Constants.ORIENT_LANDSCAPE_RIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mOrientation != mLastHandledOrientation) {
|
|
||||||
int degrees = 0;
|
|
||||||
switch (mOrientation) {
|
|
||||||
case Constants.ORIENT_LANDSCAPE_LEFT:
|
|
||||||
degrees = 90;
|
|
||||||
break;
|
|
||||||
case Constants.ORIENT_LANDSCAPE_RIGHT:
|
|
||||||
degrees = -90;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
animateViews(degrees);
|
|
||||||
mLastHandledOrientation = mOrientation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void animateViews(int degrees) {
|
|
||||||
View[] views = {mToggleCameraBtn, mToggleFlashBtn, mTogglePhotoVideoBtn, mShutterBtn, mSettingsBtn, mLastPhotoVideoPreview};
|
|
||||||
for (View view : views) {
|
|
||||||
rotate(view, degrees);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rotate(View view, int degrees) {
|
|
||||||
view.animate().rotation(degrees).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkCameraAvailable() {
|
|
||||||
if (!mIsCameraAvailable) {
|
|
||||||
Utils.Companion.showToast(getApplicationContext(), R.string.camera_unavailable);
|
|
||||||
}
|
|
||||||
return mIsCameraAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFlashAvailable(boolean available) {
|
|
||||||
if (available) {
|
|
||||||
mToggleFlashBtn.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
mToggleFlashBtn.setVisibility(View.INVISIBLE);
|
|
||||||
disableFlash();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIsCameraAvailable(boolean available) {
|
|
||||||
mIsCameraAvailable = available;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCurrentOrientation() {
|
|
||||||
return mOrientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void videoSaved(Uri uri) {
|
|
||||||
setupPreviewImage(mIsInPhotoMode);
|
|
||||||
if (mIsVideoCaptureIntent) {
|
|
||||||
final Intent intent = new Intent();
|
|
||||||
intent.setData(uri);
|
|
||||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
setResult(RESULT_OK, intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawFocusRect(int x, int y) {
|
|
||||||
if (mFocusRectView != null) {
|
|
||||||
mFocusRectView.drawFocusRect(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mediaSaved(String path) {
|
|
||||||
final String[] paths = {path};
|
|
||||||
MediaScannerConnection.scanFile(getApplicationContext(), paths, null, this);
|
|
||||||
|
|
||||||
if (mIsImageCaptureIntent) {
|
|
||||||
setResult(RESULT_OK);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
Config.Companion.newInstance(getApplicationContext()).setFirstRun(false);
|
|
||||||
if (mPreview != null)
|
|
||||||
mPreview.releaseCamera();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onScanCompleted(String path, Uri uri) {
|
|
||||||
setupPreviewImage(mIsInPhotoMode);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,603 @@
|
|||||||
|
package com.simplemobiletools.camera.activities
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Matrix
|
||||||
|
import android.hardware.*
|
||||||
|
import android.media.MediaScannerConnection
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.provider.MediaStore
|
||||||
|
import android.support.v4.app.ActivityCompat
|
||||||
|
import android.view.*
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import com.simplemobiletools.camera.*
|
||||||
|
import com.simplemobiletools.camera.Preview.PreviewListener
|
||||||
|
import com.simplemobiletools.camera.views.FocusRectView
|
||||||
|
import com.simplemobiletools.filepicker.extensions.hasStoragePermission
|
||||||
|
import com.simplemobiletools.filepicker.extensions.toast
|
||||||
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class MainActivity : SimpleActivity(), SensorEventListener, PreviewListener, PhotoProcessor.MediaSavedListener, MediaScannerConnection.OnScanCompletedListener {
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val CAMERA_STORAGE_PERMISSION = 1
|
||||||
|
private val AUDIO_PERMISSION = 2
|
||||||
|
private val FADE_DELAY = 5000
|
||||||
|
|
||||||
|
lateinit var mSensorManager: SensorManager
|
||||||
|
lateinit var mFocusRectView: FocusRectView
|
||||||
|
lateinit var mTimerHandler: Handler
|
||||||
|
lateinit var mFadeHandler: Handler
|
||||||
|
lateinit var mPreview: Preview
|
||||||
|
lateinit var mRes: Resources
|
||||||
|
|
||||||
|
private var mPreviewUri: Uri? = null
|
||||||
|
private var mIsFlashEnabled = false
|
||||||
|
private var mIsInPhotoMode = false
|
||||||
|
private var mIsAskingPermissions = false
|
||||||
|
private var mIsCameraAvailable = false
|
||||||
|
private var mIsImageCaptureIntent = false
|
||||||
|
private var mIsVideoCaptureIntent = false
|
||||||
|
private var mIsHardwareShutterHandled = false
|
||||||
|
private var mCurrVideoRecTimer = 0
|
||||||
|
private var mOrientation = 0
|
||||||
|
private var mCurrCamera = 0
|
||||||
|
private var mLastHandledOrientation = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||||
|
mRes = resources
|
||||||
|
tryInitCamera()
|
||||||
|
|
||||||
|
supportActionBar?.hide()
|
||||||
|
|
||||||
|
toggle_camera.setOnClickListener { toggleCamera() }
|
||||||
|
last_photo_video_preview.setOnClickListener { showLastMediaPreview() }
|
||||||
|
toggle_flash.setOnClickListener { toggleFlash() }
|
||||||
|
shutter.setOnClickListener { shutterPressed() }
|
||||||
|
settings.setOnClickListener { launchSettings() }
|
||||||
|
toggle_photo_video.setOnClickListener { handleTogglePhotoVideo() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
|
return if (keyCode == KeyEvent.KEYCODE_CAMERA && !mIsHardwareShutterHandled) {
|
||||||
|
mIsHardwareShutterHandled = true
|
||||||
|
shutterPressed()
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
super.onKeyDown(keyCode, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_CAMERA) {
|
||||||
|
mIsHardwareShutterHandled = false
|
||||||
|
}
|
||||||
|
return super.onKeyUp(keyCode, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideToggleModeAbout() {
|
||||||
|
toggle_photo_video.visibility = View.GONE
|
||||||
|
settings.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryInitCamera() {
|
||||||
|
if (hasCameraAndStoragePermission()) {
|
||||||
|
initializeCamera()
|
||||||
|
handleIntent()
|
||||||
|
} else {
|
||||||
|
val permissions = ArrayList<String>(2)
|
||||||
|
if (!Utils.hasCameraPermission(applicationContext)) {
|
||||||
|
permissions.add(Manifest.permission.CAMERA)
|
||||||
|
}
|
||||||
|
if (!hasStoragePermission()) {
|
||||||
|
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
}
|
||||||
|
ActivityCompat.requestPermissions(this, permissions.toTypedArray(), CAMERA_STORAGE_PERMISSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent() {
|
||||||
|
if (intent != null && intent.action != null) {
|
||||||
|
if (intent.extras != null && intent.action == MediaStore.ACTION_IMAGE_CAPTURE || intent.action == MediaStore.ACTION_IMAGE_CAPTURE_SECURE) {
|
||||||
|
mIsImageCaptureIntent = true
|
||||||
|
hideToggleModeAbout()
|
||||||
|
val output = intent.extras.get(MediaStore.EXTRA_OUTPUT)
|
||||||
|
if (output != null && output is Uri) {
|
||||||
|
mPreview.setTargetUri(output)
|
||||||
|
}
|
||||||
|
} else if (intent.action == MediaStore.ACTION_VIDEO_CAPTURE) {
|
||||||
|
mIsVideoCaptureIntent = true
|
||||||
|
hideToggleModeAbout()
|
||||||
|
shutter.setImageDrawable(mRes.getDrawable(R.mipmap.video_rec))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeCamera() {
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
|
if (Utils.hasNavBar(mRes) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
|
val lp = btn_holder.layoutParams as RelativeLayout.LayoutParams
|
||||||
|
lp.setMargins(0, 0, 0, lp.bottomMargin + Utils.getNavBarHeight(mRes))
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrCamera = config.lastUsedCamera
|
||||||
|
mPreview = Preview(this, camera_view, this)
|
||||||
|
mPreview.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
view_holder.addView(mPreview)
|
||||||
|
toggle_camera.setImageResource(if (mCurrCamera == Camera.CameraInfo.CAMERA_FACING_BACK) R.mipmap.camera_front else R.mipmap.camera_back)
|
||||||
|
|
||||||
|
mFocusRectView = FocusRectView(applicationContext)
|
||||||
|
view_holder.addView(mFocusRectView)
|
||||||
|
|
||||||
|
mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||||
|
mIsInPhotoMode = true
|
||||||
|
mTimerHandler = Handler()
|
||||||
|
mFadeHandler = Handler()
|
||||||
|
mIsFlashEnabled = config.lastFlashlightState
|
||||||
|
setupPreviewImage(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasCameraAndStoragePermission() = Utils.hasCameraPermission(applicationContext) && hasStoragePermission()
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
mIsAskingPermissions = false
|
||||||
|
|
||||||
|
if (requestCode == CAMERA_STORAGE_PERMISSION) {
|
||||||
|
if (hasCameraAndStoragePermission()) {
|
||||||
|
initializeCamera()
|
||||||
|
handleIntent()
|
||||||
|
} else {
|
||||||
|
toast(R.string.no_permissions)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else if (requestCode == AUDIO_PERMISSION) {
|
||||||
|
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
togglePhotoVideo()
|
||||||
|
} else {
|
||||||
|
toast(R.string.no_audio_permissions)
|
||||||
|
if (mIsVideoCaptureIntent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleCamera() {
|
||||||
|
if (!checkCameraAvailable()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrCamera == Camera.CameraInfo.CAMERA_FACING_BACK) {
|
||||||
|
mCurrCamera = Camera.CameraInfo.CAMERA_FACING_FRONT
|
||||||
|
} else {
|
||||||
|
mCurrCamera = Camera.CameraInfo.CAMERA_FACING_BACK
|
||||||
|
}
|
||||||
|
|
||||||
|
config.lastUsedCamera = mCurrCamera
|
||||||
|
var newIconId = R.mipmap.camera_front
|
||||||
|
mPreview.releaseCamera()
|
||||||
|
if (mPreview.setCamera(mCurrCamera)) {
|
||||||
|
if (mCurrCamera == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||||
|
newIconId = R.mipmap.camera_back
|
||||||
|
}
|
||||||
|
toggle_camera.setImageResource(newIconId)
|
||||||
|
disableFlash()
|
||||||
|
hideTimer()
|
||||||
|
} else {
|
||||||
|
toast(R.string.camera_switch_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showLastMediaPreview() {
|
||||||
|
if (mPreviewUri == null)
|
||||||
|
return
|
||||||
|
|
||||||
|
try {
|
||||||
|
val REVIEW_ACTION = "com.android.camera.action.REVIEW"
|
||||||
|
val intent = Intent(REVIEW_ACTION, mPreviewUri)
|
||||||
|
startActivity(intent)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, mPreviewUri)
|
||||||
|
if (intent.resolveActivity(packageManager) != null) {
|
||||||
|
startActivity(intent)
|
||||||
|
} else {
|
||||||
|
toast(R.string.no_gallery_app_available)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleFlash() {
|
||||||
|
if (!checkCameraAvailable()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsFlashEnabled = !mIsFlashEnabled
|
||||||
|
checkFlash()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkFlash() {
|
||||||
|
if (mIsFlashEnabled) {
|
||||||
|
enableFlash()
|
||||||
|
} else {
|
||||||
|
disableFlash()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun disableFlash() {
|
||||||
|
mPreview.disableFlash()
|
||||||
|
toggle_flash.setImageResource(R.mipmap.flash_off)
|
||||||
|
mIsFlashEnabled = false
|
||||||
|
config.lastFlashlightState = mIsFlashEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enableFlash() {
|
||||||
|
mPreview.enableFlash()
|
||||||
|
toggle_flash.setImageResource(R.mipmap.flash_on)
|
||||||
|
mIsFlashEnabled = true
|
||||||
|
config.lastFlashlightState = mIsFlashEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shutterPressed() {
|
||||||
|
if (checkCameraAvailable()) {
|
||||||
|
handleShutter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleShutter() {
|
||||||
|
if (mIsInPhotoMode) {
|
||||||
|
toggleBottomButtons(true)
|
||||||
|
mPreview.takePicture()
|
||||||
|
Handler().postDelayed({ toggleBottomButtons(false) }, Preview.PHOTO_PREVIEW_LENGTH.toLong())
|
||||||
|
} else {
|
||||||
|
val isRecording = mPreview.toggleRecording()
|
||||||
|
if (isRecording) {
|
||||||
|
shutter.setImageDrawable(mRes.getDrawable(R.mipmap.video_stop))
|
||||||
|
toggle_camera.visibility = View.INVISIBLE
|
||||||
|
showTimer()
|
||||||
|
} else {
|
||||||
|
shutter.setImageDrawable(mRes.getDrawable(R.mipmap.video_rec))
|
||||||
|
toggle_camera.visibility = View.VISIBLE
|
||||||
|
hideTimer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleBottomButtons(hide: Boolean) {
|
||||||
|
val alpha = if (hide) 0f else 1f
|
||||||
|
shutter.animate().alpha(alpha).start()
|
||||||
|
toggle_camera.animate().alpha(alpha).start()
|
||||||
|
toggle_flash.animate().alpha(alpha).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun launchSettings() {
|
||||||
|
if (settings.alpha == 1f) {
|
||||||
|
val intent = Intent(applicationContext, SettingsActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
} else {
|
||||||
|
fadeInButtons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleTogglePhotoVideo() {
|
||||||
|
togglePhotoVideo()
|
||||||
|
checkButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun togglePhotoVideo() {
|
||||||
|
if (!checkCameraAvailable()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Utils.hasAudioPermission(applicationContext)) {
|
||||||
|
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), AUDIO_PERMISSION)
|
||||||
|
mIsAskingPermissions = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsVideoCaptureIntent)
|
||||||
|
mPreview.trySwitchToVideo()
|
||||||
|
|
||||||
|
disableFlash()
|
||||||
|
hideTimer()
|
||||||
|
mIsInPhotoMode = !mIsInPhotoMode
|
||||||
|
toggle_camera.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkButtons() {
|
||||||
|
if (mIsInPhotoMode) {
|
||||||
|
initPhotoButtons()
|
||||||
|
} else {
|
||||||
|
tryInitVideoButtons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initPhotoButtons() {
|
||||||
|
toggle_photo_video.setImageDrawable(mRes.getDrawable(R.mipmap.videocam))
|
||||||
|
shutter.setImageDrawable(mRes.getDrawable(R.mipmap.camera))
|
||||||
|
mPreview.initPhotoMode()
|
||||||
|
setupPreviewImage(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryInitVideoButtons() {
|
||||||
|
if (mPreview.initRecorder()) {
|
||||||
|
initVideoButtons()
|
||||||
|
} else {
|
||||||
|
if (!mIsVideoCaptureIntent) {
|
||||||
|
toast(R.string.video_mode_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initVideoButtons() {
|
||||||
|
toggle_photo_video.setImageDrawable(mRes.getDrawable(R.mipmap.photo))
|
||||||
|
toggle_camera.visibility = View.VISIBLE
|
||||||
|
shutter.setImageDrawable(mRes.getDrawable(R.mipmap.video_rec))
|
||||||
|
checkFlash()
|
||||||
|
setupPreviewImage(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupPreviewImage(isPhoto: Boolean) {
|
||||||
|
val uri = if (isPhoto) MediaStore.Images.Media.EXTERNAL_CONTENT_URI else MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||||
|
val lastMediaId = getLastMediaId(uri)
|
||||||
|
if (lastMediaId == 0L) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val cr = contentResolver
|
||||||
|
mPreviewUri = Uri.withAppendedPath(uri, lastMediaId.toString())
|
||||||
|
var tmb: Bitmap
|
||||||
|
|
||||||
|
if (isPhoto) {
|
||||||
|
tmb = MediaStore.Images.Thumbnails.getThumbnail(cr, lastMediaId, MediaStore.Images.Thumbnails.MICRO_KIND, null)
|
||||||
|
val rotationDegrees = getImageRotation()
|
||||||
|
tmb = rotateThumbnail(tmb, rotationDegrees)
|
||||||
|
} else {
|
||||||
|
tmb = MediaStore.Video.Thumbnails.getThumbnail(cr, lastMediaId, MediaStore.Video.Thumbnails.MICRO_KIND, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
setPreviewImage(tmb)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getImageRotation(): Int {
|
||||||
|
val projection = arrayOf(MediaStore.Images.ImageColumns.ORIENTATION)
|
||||||
|
var cursor: Cursor? = null
|
||||||
|
try {
|
||||||
|
cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null)
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
val orientationIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION)
|
||||||
|
return cursor.getInt(orientationIndex)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
cursor?.close()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rotateThumbnail(tmb: Bitmap, degrees: Int): Bitmap {
|
||||||
|
if (degrees == 0)
|
||||||
|
return tmb
|
||||||
|
|
||||||
|
val matrix = Matrix()
|
||||||
|
matrix.setRotate(degrees.toFloat(), (tmb.width / 2).toFloat(), (tmb.height / 2).toFloat())
|
||||||
|
return Bitmap.createBitmap(tmb, 0, 0, tmb.width, tmb.height, matrix, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setPreviewImage(bmp: Bitmap?) {
|
||||||
|
if (bmp != null) {
|
||||||
|
last_photo_video_preview.post { last_photo_video_preview.setImageBitmap(bmp) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLastMediaId(uri: Uri): Long {
|
||||||
|
val projection = arrayOf(MediaStore.Images.ImageColumns._ID)
|
||||||
|
var cursor: Cursor? = null
|
||||||
|
try {
|
||||||
|
cursor = contentResolver.query(uri, projection, null, null, "${MediaStore.Images.ImageColumns.DATE_TAKEN} DESC")
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
val idIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID)
|
||||||
|
return cursor.getLong(idIndex)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
cursor?.close()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleFadeOut() = mFadeHandler.postDelayed({ fadeOutButtons() }, FADE_DELAY.toLong())
|
||||||
|
|
||||||
|
private fun fadeOutButtons() {
|
||||||
|
fadeAnim(settings, .5f)
|
||||||
|
fadeAnim(toggle_photo_video, .0f)
|
||||||
|
fadeAnim(last_photo_video_preview, .0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fadeInButtons() {
|
||||||
|
fadeAnim(settings, 1f)
|
||||||
|
fadeAnim(toggle_photo_video, 1f)
|
||||||
|
fadeAnim(last_photo_video_preview, 1f)
|
||||||
|
scheduleFadeOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fadeAnim(view: View, value: Float) {
|
||||||
|
view.animate().alpha(value).start()
|
||||||
|
view.isClickable = value != .0f
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideNavigationBarIcons() {
|
||||||
|
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideTimer() {
|
||||||
|
video_rec_curr_timer.text = Utils.formatSeconds(0)
|
||||||
|
video_rec_curr_timer.visibility = View.GONE
|
||||||
|
mCurrVideoRecTimer = 0
|
||||||
|
mTimerHandler.removeCallbacksAndMessages(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showTimer() {
|
||||||
|
video_rec_curr_timer.visibility = View.VISIBLE
|
||||||
|
setupTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupTimer() {
|
||||||
|
runOnUiThread(object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
video_rec_curr_timer.text = Utils.formatSeconds(mCurrVideoRecTimer++)
|
||||||
|
mTimerHandler.postDelayed(this, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (hasCameraAndStoragePermission()) {
|
||||||
|
resumeCameraItems()
|
||||||
|
setupPreviewImage(mIsInPhotoMode)
|
||||||
|
scheduleFadeOut()
|
||||||
|
|
||||||
|
if (mIsVideoCaptureIntent && mIsInPhotoMode) {
|
||||||
|
togglePhotoVideo()
|
||||||
|
checkButtons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resumeCameraItems() {
|
||||||
|
val cnt = Camera.getNumberOfCameras()
|
||||||
|
if (cnt == 1) {
|
||||||
|
toggle_camera.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPreview.setCamera(mCurrCamera)) {
|
||||||
|
hideNavigationBarIcons()
|
||||||
|
checkFlash()
|
||||||
|
|
||||||
|
val accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
|
||||||
|
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME)
|
||||||
|
|
||||||
|
if (!mIsInPhotoMode) {
|
||||||
|
initVideoButtons()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast(R.string.camera_switch_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
if (!hasCameraAndStoragePermission() || mIsAskingPermissions)
|
||||||
|
return
|
||||||
|
|
||||||
|
mFadeHandler.removeCallbacksAndMessages(null)
|
||||||
|
|
||||||
|
hideTimer()
|
||||||
|
mPreview.releaseCamera()
|
||||||
|
mSensorManager.unregisterListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSensorChanged(event: SensorEvent) {
|
||||||
|
if (event.values[0] < 6.5 && event.values[0] > -6.5) {
|
||||||
|
mOrientation = Constants.ORIENT_PORTRAIT
|
||||||
|
} else {
|
||||||
|
if (event.values[0] > 0) {
|
||||||
|
mOrientation = Constants.ORIENT_LANDSCAPE_LEFT
|
||||||
|
} else {
|
||||||
|
mOrientation = Constants.ORIENT_LANDSCAPE_RIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOrientation != mLastHandledOrientation) {
|
||||||
|
val degrees = when (mOrientation) {
|
||||||
|
Constants.ORIENT_LANDSCAPE_LEFT -> 90
|
||||||
|
Constants.ORIENT_LANDSCAPE_RIGHT -> -90
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
animateViews(degrees)
|
||||||
|
mLastHandledOrientation = mOrientation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun animateViews(degrees: Int) {
|
||||||
|
val views = arrayOf<View>(toggle_camera, toggle_flash, toggle_photo_video, shutter, settings, last_photo_video_preview)
|
||||||
|
for (view in views) {
|
||||||
|
rotate(view, degrees)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rotate(view: View, degrees: Int) = view.animate().rotation(degrees.toFloat()).start()
|
||||||
|
|
||||||
|
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCameraAvailable(): Boolean {
|
||||||
|
if (!mIsCameraAvailable) {
|
||||||
|
toast(R.string.camera_unavailable)
|
||||||
|
}
|
||||||
|
return mIsCameraAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setFlashAvailable(available: Boolean) {
|
||||||
|
if (available) {
|
||||||
|
toggle_flash.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
toggle_flash.visibility = View.INVISIBLE
|
||||||
|
disableFlash()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setIsCameraAvailable(available: Boolean) {
|
||||||
|
mIsCameraAvailable = available
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCurrentOrientation() = mOrientation
|
||||||
|
|
||||||
|
override fun videoSaved(uri: Uri) {
|
||||||
|
setupPreviewImage(mIsInPhotoMode)
|
||||||
|
if (mIsVideoCaptureIntent) {
|
||||||
|
Intent().apply {
|
||||||
|
data = uri
|
||||||
|
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
setResult(Activity.RESULT_OK, this)
|
||||||
|
}
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawFocusRect(x: Int, y: Int) = mFocusRectView.drawFocusRect(x, y)
|
||||||
|
|
||||||
|
override fun mediaSaved(path: String) {
|
||||||
|
val paths = arrayOf(path)
|
||||||
|
MediaScannerConnection.scanFile(applicationContext, paths, null, this)
|
||||||
|
|
||||||
|
if (mIsImageCaptureIntent) {
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
config.isFirstRun = false
|
||||||
|
mPreview.releaseCamera()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScanCompleted(path: String, uri: Uri) = setupPreviewImage(mIsInPhotoMode)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user