mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 14:47:29 +00:00
Convert CameraActivity to kotlin
This commit is contained in:
parent
f52cebf419
commit
cf0c420801
@ -1,239 +1,211 @@
|
|||||||
package awais.instagrabber.activities;
|
package awais.instagrabber.activities
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.content.Intent
|
||||||
import android.content.Context;
|
import android.content.res.Configuration
|
||||||
import android.content.Intent;
|
import android.hardware.display.DisplayManager
|
||||||
import android.content.res.Configuration;
|
import android.hardware.display.DisplayManager.DisplayListener
|
||||||
import android.hardware.display.DisplayManager;
|
import android.media.MediaScannerConnection
|
||||||
import android.media.MediaScannerConnection;
|
import android.net.Uri
|
||||||
import android.net.Uri;
|
import android.os.Bundle
|
||||||
import android.os.Bundle;
|
import android.util.Log
|
||||||
import android.util.Log;
|
import android.view.LayoutInflater
|
||||||
import android.view.LayoutInflater;
|
import android.webkit.MimeTypeMap
|
||||||
import android.webkit.MimeTypeMap;
|
import androidx.camera.core.*
|
||||||
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import awais.instagrabber.databinding.ActivityCameraBinding
|
||||||
|
import awais.instagrabber.utils.DirectoryUtils
|
||||||
|
import awais.instagrabber.utils.PermissionUtils
|
||||||
|
import awais.instagrabber.utils.Utils
|
||||||
|
import awais.instagrabber.utils.extensions.TAG
|
||||||
|
import com.google.common.io.Files
|
||||||
|
import java.io.File
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.ExecutionException
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
class CameraActivity : BaseLanguageActivity() {
|
||||||
import androidx.annotation.Nullable;
|
private lateinit var binding: ActivityCameraBinding
|
||||||
import androidx.camera.core.CameraInfoUnavailableException;
|
private lateinit var outputDirectory: File
|
||||||
import androidx.camera.core.CameraSelector;
|
private lateinit var displayManager: DisplayManager
|
||||||
import androidx.camera.core.ImageCapture;
|
private lateinit var cameraExecutor: ExecutorService
|
||||||
import androidx.camera.core.ImageCaptureException;
|
|
||||||
import androidx.camera.core.Preview;
|
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
private var imageCapture: ImageCapture? = null
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
private var displayId = -1
|
||||||
|
private var cameraProvider: ProcessCameraProvider? = null
|
||||||
|
private var lensFacing = 0
|
||||||
|
|
||||||
import java.io.File;
|
private val cameraRequestCode = 100
|
||||||
import java.text.SimpleDateFormat;
|
private val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
|
||||||
import java.util.Locale;
|
private val displayListener: DisplayListener = object : DisplayListener {
|
||||||
import java.util.concurrent.ExecutionException;
|
override fun onDisplayAdded(displayId: Int) {}
|
||||||
import java.util.concurrent.ExecutorService;
|
override fun onDisplayRemoved(displayId: Int) {}
|
||||||
import java.util.concurrent.Executors;
|
override fun onDisplayChanged(displayId: Int) {
|
||||||
|
if (displayId == this@CameraActivity.displayId) {
|
||||||
import awais.instagrabber.databinding.ActivityCameraBinding;
|
imageCapture?.targetRotation = binding.root.display.rotation
|
||||||
import awais.instagrabber.utils.DirectoryUtils;
|
|
||||||
import awais.instagrabber.utils.PermissionUtils;
|
|
||||||
import awais.instagrabber.utils.Utils;
|
|
||||||
|
|
||||||
public class CameraActivity extends BaseLanguageActivity {
|
|
||||||
private static final String TAG = CameraActivity.class.getSimpleName();
|
|
||||||
private static final int CAMERA_REQUEST_CODE = 100;
|
|
||||||
private static final String FILE_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS";
|
|
||||||
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat(FILE_FORMAT, Locale.US);
|
|
||||||
|
|
||||||
private ActivityCameraBinding binding;
|
|
||||||
private ImageCapture imageCapture;
|
|
||||||
private File outputDirectory;
|
|
||||||
private ExecutorService cameraExecutor;
|
|
||||||
private int displayId = -1;
|
|
||||||
|
|
||||||
private final DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() {
|
|
||||||
@Override
|
|
||||||
public void onDisplayAdded(final int displayId) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisplayRemoved(final int displayId) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisplayChanged(final int displayId) {
|
|
||||||
if (displayId == CameraActivity.this.displayId) {
|
|
||||||
imageCapture.setTargetRotation(binding.getRoot().getDisplay().getRotation());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
private DisplayManager displayManager;
|
|
||||||
private ProcessCameraProvider cameraProvider;
|
|
||||||
private int lensFacing;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
binding = ActivityCameraBinding.inflate(LayoutInflater.from(getBaseContext()));
|
|
||||||
setContentView(binding.getRoot());
|
|
||||||
Utils.transparentStatusBar(this, true, false);
|
|
||||||
displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
|
|
||||||
outputDirectory = DirectoryUtils.getOutputMediaDirectory(this, "Camera");
|
|
||||||
cameraExecutor = Executors.newSingleThreadExecutor();
|
|
||||||
displayManager.registerDisplayListener(displayListener, null);
|
|
||||||
binding.viewFinder.post(() -> {
|
|
||||||
displayId = binding.viewFinder.getDisplay().getDisplayId();
|
|
||||||
updateUi();
|
|
||||||
checkPermissionsAndSetupCamera();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
protected void onResume() {
|
super.onCreate(savedInstanceState)
|
||||||
super.onResume();
|
binding = ActivityCameraBinding.inflate(LayoutInflater.from(baseContext))
|
||||||
|
setContentView(binding.root)
|
||||||
|
Utils.transparentStatusBar(this, true, false)
|
||||||
|
displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager
|
||||||
|
outputDirectory = DirectoryUtils.getOutputMediaDirectory(this, "Camera")
|
||||||
|
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
displayManager.registerDisplayListener(displayListener, null)
|
||||||
|
binding.viewFinder.post {
|
||||||
|
displayId = binding.viewFinder.display.displayId
|
||||||
|
updateUi()
|
||||||
|
checkPermissionsAndSetupCamera()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
// Make sure that all permissions are still present, since the
|
// Make sure that all permissions are still present, since the
|
||||||
// user could have removed them while the app was in paused state.
|
// user could have removed them while the app was in paused state.
|
||||||
if (!PermissionUtils.hasCameraPerms(this)) {
|
if (!PermissionUtils.hasCameraPerms(this)) {
|
||||||
PermissionUtils.requestCameraPerms(this, CAMERA_REQUEST_CODE);
|
PermissionUtils.requestCameraPerms(this, cameraRequestCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
public void onConfigurationChanged(@NonNull final Configuration newConfig) {
|
super.onConfigurationChanged(newConfig)
|
||||||
super.onConfigurationChanged(newConfig);
|
|
||||||
// Redraw the camera UI controls
|
// Redraw the camera UI controls
|
||||||
updateUi();
|
updateUi()
|
||||||
|
|
||||||
// Enable or disable switching between cameras
|
// Enable or disable switching between cameras
|
||||||
updateCameraSwitchButton();
|
updateCameraSwitchButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun onDestroy() {
|
||||||
protected void onDestroy() {
|
super.onDestroy()
|
||||||
super.onDestroy();
|
Utils.transparentStatusBar(this, false, false)
|
||||||
Utils.transparentStatusBar(this, false, false);
|
cameraExecutor.shutdown()
|
||||||
cameraExecutor.shutdown();
|
displayManager.unregisterDisplayListener(displayListener)
|
||||||
displayManager.unregisterDisplayListener(displayListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUi() {
|
private fun updateUi() {
|
||||||
binding.cameraCaptureButton.setOnClickListener(v -> takePhoto());
|
binding.cameraCaptureButton.setOnClickListener { takePhoto() }
|
||||||
// Disable the button until the camera is set up
|
// Disable the button until the camera is set up
|
||||||
binding.switchCamera.setEnabled(false);
|
binding.switchCamera.isEnabled = false
|
||||||
// Listener for button used to switch cameras. Only called if the button is enabled
|
// Listener for button used to switch cameras. Only called if the button is enabled
|
||||||
binding.switchCamera.setOnClickListener(v -> {
|
binding.switchCamera.setOnClickListener {
|
||||||
lensFacing = CameraSelector.LENS_FACING_FRONT == lensFacing ? CameraSelector.LENS_FACING_BACK
|
lensFacing = if (CameraSelector.LENS_FACING_FRONT == lensFacing) CameraSelector.LENS_FACING_BACK else CameraSelector.LENS_FACING_FRONT
|
||||||
: CameraSelector.LENS_FACING_FRONT;
|
|
||||||
// Re-bind use cases to update selected camera
|
// Re-bind use cases to update selected camera
|
||||||
bindCameraUseCases();
|
bindCameraUseCases()
|
||||||
});
|
}
|
||||||
binding.close.setOnClickListener(v -> {
|
binding.close.setOnClickListener {
|
||||||
setResult(Activity.RESULT_CANCELED);
|
setResult(RESULT_CANCELED)
|
||||||
finish();
|
finish()
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPermissionsAndSetupCamera() {
|
private fun checkPermissionsAndSetupCamera() {
|
||||||
if (PermissionUtils.hasCameraPerms(this)) {
|
if (PermissionUtils.hasCameraPerms(this)) {
|
||||||
setupCamera();
|
setupCamera()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
PermissionUtils.requestCameraPerms(this, CAMERA_REQUEST_CODE);
|
PermissionUtils.requestCameraPerms(this, cameraRequestCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
if (requestCode == CAMERA_REQUEST_CODE) {
|
if (requestCode == cameraRequestCode) {
|
||||||
if (PermissionUtils.hasCameraPerms(this)) {
|
if (PermissionUtils.hasCameraPerms(this)) {
|
||||||
setupCamera();
|
setupCamera()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupCamera() {
|
private fun setupCamera() {
|
||||||
final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
|
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||||
cameraProviderFuture.addListener(() -> {
|
cameraProviderFuture.addListener({
|
||||||
try {
|
try {
|
||||||
cameraProvider = cameraProviderFuture.get();
|
cameraProvider = cameraProviderFuture.get()
|
||||||
// Select lensFacing depending on the available cameras
|
// Select lensFacing depending on the available cameras
|
||||||
lensFacing = -1;
|
lensFacing = -1
|
||||||
if (hasBackCamera()) {
|
if (hasBackCamera()) {
|
||||||
lensFacing = CameraSelector.LENS_FACING_BACK;
|
lensFacing = CameraSelector.LENS_FACING_BACK
|
||||||
} else if (hasFrontCamera()) {
|
} else if (hasFrontCamera()) {
|
||||||
lensFacing = CameraSelector.LENS_FACING_FRONT;
|
lensFacing = CameraSelector.LENS_FACING_FRONT
|
||||||
}
|
|
||||||
if (lensFacing == -1) {
|
|
||||||
throw new IllegalStateException("Back and front camera are unavailable");
|
|
||||||
}
|
}
|
||||||
|
check(lensFacing != -1) { "Back and front camera are unavailable" }
|
||||||
// Enable or disable switching between cameras
|
// Enable or disable switching between cameras
|
||||||
updateCameraSwitchButton();
|
updateCameraSwitchButton()
|
||||||
// Build and bind the camera use cases
|
// Build and bind the camera use cases
|
||||||
bindCameraUseCases();
|
bindCameraUseCases()
|
||||||
} catch (ExecutionException | InterruptedException | CameraInfoUnavailableException e) {
|
} catch (e: ExecutionException) {
|
||||||
Log.e(TAG, "setupCamera: ", e);
|
Log.e(TAG, "setupCamera: ", e)
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
Log.e(TAG, "setupCamera: ", e)
|
||||||
|
} catch (e: CameraInfoUnavailableException) {
|
||||||
|
Log.e(TAG, "setupCamera: ", e)
|
||||||
}
|
}
|
||||||
|
}, ContextCompat.getMainExecutor(this))
|
||||||
}, ContextCompat.getMainExecutor(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindCameraUseCases() {
|
private fun bindCameraUseCases() {
|
||||||
final int rotation = binding.viewFinder.getDisplay().getRotation();
|
val rotation = binding.viewFinder.display.rotation
|
||||||
|
|
||||||
// CameraSelector
|
// CameraSelector
|
||||||
final CameraSelector cameraSelector = new CameraSelector.Builder()
|
val cameraSelector = CameraSelector.Builder()
|
||||||
.requireLensFacing(lensFacing)
|
.requireLensFacing(lensFacing)
|
||||||
.build();
|
.build()
|
||||||
|
|
||||||
// Preview
|
// Preview
|
||||||
final Preview preview = new Preview.Builder()
|
val preview = Preview.Builder() // Set initial target rotation
|
||||||
// Set initial target rotation
|
.setTargetRotation(rotation)
|
||||||
.setTargetRotation(rotation)
|
.build()
|
||||||
.build();
|
|
||||||
|
|
||||||
// ImageCapture
|
// ImageCapture
|
||||||
imageCapture = new ImageCapture.Builder()
|
imageCapture = ImageCapture.Builder()
|
||||||
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) // Set initial target rotation, we will have to call this again if rotation changes
|
||||||
// Set initial target rotation, we will have to call this again if rotation changes
|
// during the lifecycle of this use case
|
||||||
// during the lifecycle of this use case
|
.setTargetRotation(rotation)
|
||||||
.setTargetRotation(rotation)
|
.build()
|
||||||
.build();
|
cameraProvider?.unbindAll()
|
||||||
|
cameraProvider?.bindToLifecycle(this, cameraSelector, preview, imageCapture)
|
||||||
cameraProvider.unbindAll();
|
preview.setSurfaceProvider(binding.viewFinder.surfaceProvider)
|
||||||
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);
|
|
||||||
|
|
||||||
preview.setSurfaceProvider(binding.viewFinder.getSurfaceProvider());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void takePhoto() {
|
private fun takePhoto() {
|
||||||
if (imageCapture == null) return;
|
if (imageCapture == null) return
|
||||||
final File photoFile = new File(outputDirectory, SIMPLE_DATE_FORMAT.format(System.currentTimeMillis()) + ".jpg");
|
val photoFile = File(outputDirectory, simpleDateFormat.format(System.currentTimeMillis()) + ".jpg")
|
||||||
final ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build();
|
val outputFileOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
|
||||||
imageCapture.takePicture(
|
imageCapture?.takePicture(
|
||||||
outputFileOptions,
|
outputFileOptions,
|
||||||
cameraExecutor,
|
cameraExecutor,
|
||||||
new ImageCapture.OnImageSavedCallback() {
|
object : ImageCapture.OnImageSavedCallback {
|
||||||
@Override
|
@Suppress("UnstableApiUsage")
|
||||||
public void onImageSaved(@NonNull final ImageCapture.OutputFileResults outputFileResults) {
|
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||||
final Uri uri = Uri.fromFile(photoFile);
|
val uri = Uri.fromFile(photoFile)
|
||||||
//noinspection UnstableApiUsage
|
val mimeType = MimeTypeMap.getSingleton()
|
||||||
final String mimeType = MimeTypeMap.getSingleton()
|
.getMimeTypeFromExtension(Files.getFileExtension(photoFile.name))
|
||||||
.getMimeTypeFromExtension(Files.getFileExtension(photoFile.getName()));
|
MediaScannerConnection.scanFile(
|
||||||
MediaScannerConnection.scanFile(
|
this@CameraActivity,
|
||||||
CameraActivity.this,
|
arrayOf(photoFile.absolutePath),
|
||||||
new String[]{photoFile.getAbsolutePath()},
|
arrayOf(mimeType)
|
||||||
new String[]{mimeType},
|
) { _: String?, uri1: Uri? ->
|
||||||
(path, uri1) -> {
|
Log.d(TAG, "onImageSaved: scan complete")
|
||||||
Log.d(TAG, "onImageSaved: scan complete");
|
val intent = Intent()
|
||||||
final Intent intent = new Intent();
|
intent.data = uri1
|
||||||
intent.setData(uri1);
|
setResult(RESULT_OK, intent)
|
||||||
setResult(Activity.RESULT_OK, intent);
|
finish()
|
||||||
finish();
|
|
||||||
});
|
|
||||||
Log.d(TAG, "onImageSaved: " + uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(@NonNull final ImageCaptureException exception) {
|
|
||||||
Log.e(TAG, "onError: ", exception);
|
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "onImageSaved: $uri")
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
override fun onError(exception: ImageCaptureException) {
|
||||||
|
Log.e(TAG, "onError: ", exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
// We can only change the foreground Drawable using API level 23+ API
|
// We can only change the foreground Drawable using API level 23+ API
|
||||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
// // Display flash animation to indicate that photo was captured
|
// // Display flash animation to indicate that photo was captured
|
||||||
@ -248,29 +220,29 @@ public class CameraActivity extends BaseLanguageActivity {
|
|||||||
/**
|
/**
|
||||||
* Enabled or disabled a button to switch cameras depending on the available cameras
|
* Enabled or disabled a button to switch cameras depending on the available cameras
|
||||||
*/
|
*/
|
||||||
private void updateCameraSwitchButton() {
|
private fun updateCameraSwitchButton() {
|
||||||
try {
|
try {
|
||||||
binding.switchCamera.setEnabled(hasBackCamera() && hasFrontCamera());
|
binding.switchCamera.isEnabled = hasBackCamera() && hasFrontCamera()
|
||||||
} catch (CameraInfoUnavailableException e) {
|
} catch (e: CameraInfoUnavailableException) {
|
||||||
binding.switchCamera.setEnabled(false);
|
binding.switchCamera.isEnabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the device has an available back camera. False otherwise
|
* Returns true if the device has an available back camera. False otherwise
|
||||||
*/
|
*/
|
||||||
private boolean hasBackCamera() throws CameraInfoUnavailableException {
|
@Throws(CameraInfoUnavailableException::class)
|
||||||
if (cameraProvider == null) return false;
|
private fun hasBackCamera(): Boolean {
|
||||||
return cameraProvider.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA);
|
return if (cameraProvider == null) false else cameraProvider?.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the device has an available front camera. False otherwise
|
* Returns true if the device has an available front camera. False otherwise
|
||||||
*/
|
*/
|
||||||
private boolean hasFrontCamera() throws CameraInfoUnavailableException {
|
@Throws(CameraInfoUnavailableException::class)
|
||||||
if (cameraProvider == null) {
|
private fun hasFrontCamera(): Boolean {
|
||||||
return false;
|
return if (cameraProvider == null) {
|
||||||
}
|
false
|
||||||
return cameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA);
|
} else cameraProvider?.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA) ?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user