Преглед изворни кода

add retake, send actions and preview

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Andy Scherzinger пре 3 година
родитељ
комит
67c421a067

+ 1 - 0
app/build.gradle

@@ -190,6 +190,7 @@ dependencies {
     implementation 'androidx.camera:camera-camera2:1.0.1'
     implementation 'androidx.camera:camera-camera2:1.0.1'
     implementation 'androidx.camera:camera-lifecycle:1.0.1'
     implementation 'androidx.camera:camera-lifecycle:1.0.1'
     implementation 'androidx.camera:camera-view:1.0.0-alpha20'
     implementation 'androidx.camera:camera-view:1.0.0-alpha20'
+    implementation "androidx.exifinterface:exifinterface:1.3.3"
 
 
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
 
 

+ 98 - 17
app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java

@@ -24,12 +24,15 @@ package com.nextcloud.talk.activities;
 
 
 import android.content.Context;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 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.util.Size;
 import android.util.Size;
 import android.view.OrientationEventListener;
 import android.view.OrientationEventListener;
 import android.view.Surface;
 import android.view.Surface;
+import android.view.View;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -39,6 +42,8 @@ import com.nextcloud.talk.models.TakePictureViewModel;
 import com.nextcloud.talk.utils.FileUtils;
 import com.nextcloud.talk.utils.FileUtils;
 
 
 import java.io.File;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Date;
 import java.util.Locale;
 import java.util.Locale;
@@ -53,6 +58,7 @@ import androidx.camera.core.ImageCaptureException;
 import androidx.camera.core.Preview;
 import androidx.camera.core.Preview;
 import androidx.camera.lifecycle.ProcessCameraProvider;
 import androidx.camera.lifecycle.ProcessCameraProvider;
 import androidx.core.content.ContextCompat;
 import androidx.core.content.ContextCompat;
+import androidx.exifinterface.media.ExifInterface;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.lifecycle.ViewModelProvider;
 
 
 public class TakePhotoActivity extends AppCompatActivity {
 public class TakePhotoActivity extends AppCompatActivity {
@@ -99,7 +105,7 @@ public class TakePhotoActivity extends AppCompatActivity {
                 viewModel.isTorchEnabled()
                 viewModel.isTorchEnabled()
                     .observe(
                     .observe(
                         this,
                         this,
-                             enabled -> camera.getCameraControl().enableTorch(enabled));
+                        enabled -> camera.getCameraControl().enableTorch(enabled));
 
 
                 binding.toggleTorch.setOnClickListener((v) -> viewModel.toggleTorchEnabled());
                 binding.toggleTorch.setOnClickListener((v) -> viewModel.toggleTorchEnabled());
                 binding.switchCamera.setOnClickListener((v) -> {
                 binding.switchCamera.setOnClickListener((v) -> {
@@ -111,6 +117,20 @@ public class TakePhotoActivity extends AppCompatActivity {
                         imageCapture,
                         imageCapture,
                         preview);
                         preview);
                 });
                 });
+                binding.retake.setOnClickListener((v) -> {
+                    Uri uri = (Uri) binding.photoPreview.getTag();
+                    File photoFile = new File(uri.getPath());
+                    if (!photoFile.delete()) {
+                        Log.w(TAG, "Error deleting temp camera image");
+                    }
+                    binding.takePhoto.setEnabled(true);
+                    showCameraElements();
+                });
+                binding.send.setOnClickListener((v) -> {
+                    Uri uri = (Uri) binding.photoPreview.getTag();
+                    setResult(RESULT_OK, new Intent().setDataAndType(uri, "image/jpeg"));
+                    finish();
+                });
             } catch (IllegalArgumentException | ExecutionException | InterruptedException e) {
             } catch (IllegalArgumentException | ExecutionException | InterruptedException e) {
                 Log.e(TAG, "Error taking picture", e);
                 Log.e(TAG, "Error taking picture", e);
                 Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
                 Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
@@ -119,6 +139,28 @@ public class TakePhotoActivity extends AppCompatActivity {
         }, ContextCompat.getMainExecutor(this));
         }, ContextCompat.getMainExecutor(this));
     }
     }
 
 
+    private void showCameraElements() {
+        binding.send.setVisibility(View.GONE);
+        binding.retake.setVisibility(View.GONE);
+        binding.photoPreview.setVisibility(View.GONE);
+
+        binding.preview.setVisibility(View.VISIBLE);
+        binding.takePhoto.setVisibility(View.VISIBLE);
+        binding.switchCamera.setVisibility(View.VISIBLE);
+        binding.toggleTorch.setVisibility(View.VISIBLE);
+    }
+
+    private void showPictureProcessingElements() {
+        binding.preview.setVisibility(View.GONE);
+        binding.takePhoto.setVisibility(View.GONE);
+        binding.switchCamera.setVisibility(View.GONE);
+        binding.toggleTorch.setVisibility(View.GONE);
+
+        binding.send.setVisibility(View.VISIBLE);
+        binding.retake.setVisibility(View.VISIBLE);
+        binding.photoPreview.setVisibility(View.VISIBLE);
+    }
+
     private ImageCapture getImageCapture() {
     private ImageCapture getImageCapture() {
         final ImageCapture imageCapture = new ImageCapture.Builder().setTargetResolution(new Size(720, 1280)).build();
         final ImageCapture imageCapture = new ImageCapture.Builder().setTargetResolution(new Size(720, 1280)).build();
 
 
@@ -145,7 +187,7 @@ public class TakePhotoActivity extends AppCompatActivity {
 
 
         binding.takePhoto.setOnClickListener((v) -> {
         binding.takePhoto.setOnClickListener((v) -> {
             binding.takePhoto.setEnabled(false);
             binding.takePhoto.setEnabled(false);
-            final String photoFileName = dateFormat.format(new Date())+ ".jpg";
+            final String photoFileName = dateFormat.format(new Date()) + ".jpg";
             try {
             try {
                 final File photoFile = FileUtils.getTempCacheFile(this, "photos/" + photoFileName);
                 final File photoFile = FileUtils.getTempCacheFile(this, "photos/" + photoFileName);
                 final ImageCapture.OutputFileOptions options =
                 final ImageCapture.OutputFileOptions options =
@@ -155,24 +197,33 @@ public class TakePhotoActivity extends AppCompatActivity {
                     ContextCompat.getMainExecutor(this),
                     ContextCompat.getMainExecutor(this),
                     new ImageCapture.OnImageSavedCallback() {
                     new ImageCapture.OnImageSavedCallback() {
 
 
-                    @Override
-                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
-                        final Uri savedUri = Uri.fromFile(photoFile);
-                        Log.i(TAG, "onImageSaved - savedUri:" + savedUri);
-                        setResult(RESULT_OK, new Intent().setDataAndType(savedUri, "image/jpeg"));
-                        finish();
-                    }
+                        @Override
+                        public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
+                            final Uri savedUri = Uri.fromFile(photoFile);
+                            Log.i(TAG, "onImageSaved - savedUri:" + savedUri);
+                            BitmapFactory.Options options = new BitmapFactory.Options();
+                            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+                            try {
+                                binding.photoPreview.setImageBitmap(
+                                    BitmapFactory.decodeStream(new FileInputStream(photoFile), null, options));
+                                binding.photoPreview.setRotation(getImageOrientation(photoFile));
+                                binding.photoPreview.setTag(savedUri);
+                                showPictureProcessingElements();
+                            } catch (FileNotFoundException e) {
+                                Log.w(TAG, "Error reading image", e);
+                            }
+                        }
 
 
-                    @Override
-                    public void onError(@NonNull ImageCaptureException e) {
-                        Log.e(TAG, "Error", e);
+                        @Override
+                        public void onError(@NonNull ImageCaptureException e) {
+                            Log.e(TAG, "Error", e);
 
 
-                        if(!photoFile.delete()) {
-                            Log.w(TAG, "Deleting picture failed");
+                            if (!photoFile.delete()) {
+                                Log.w(TAG, "Deleting picture failed");
+                            }
+                            binding.takePhoto.setEnabled(true);
                         }
                         }
-                        binding.takePhoto.setEnabled(true);
-                    }
-                });
+                    });
             } catch (Exception e) {
             } catch (Exception e) {
                 Toast.makeText(this, R.string.take_photo_error_deleting_picture, Toast.LENGTH_SHORT).show();
                 Toast.makeText(this, R.string.take_photo_error_deleting_picture, Toast.LENGTH_SHORT).show();
             }
             }
@@ -181,6 +232,36 @@ public class TakePhotoActivity extends AppCompatActivity {
         return imageCapture;
         return imageCapture;
     }
     }
 
 
+    public int getImageOrientation(File imageFile) {
+        int rotate = 0;
+        try {
+            ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
+            int orientation = exif.getAttributeInt(
+                ExifInterface.TAG_ORIENTATION,
+                ExifInterface.ORIENTATION_NORMAL);
+
+            switch (orientation) {
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    rotate = 270;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    rotate = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    rotate = 90;
+                    break;
+                default:
+                    rotate = 0;
+                    break;
+            }
+
+            Log.i(TAG, "ImageOrientation - Exif orientation: " + orientation + " - " + "Rotate value: " + rotate);
+        } catch (Exception e) {
+            Log.w(TAG, "Error calculation rotation value");
+        }
+        return rotate;
+    }
+
     private Preview getPreview() {
     private Preview getPreview() {
         Preview preview = new Preview.Builder().build();
         Preview preview = new Preview.Builder().build();
         preview.setSurfaceProvider(binding.preview.getSurfaceProvider());
         preview.setSurfaceProvider(binding.preview.getSurfaceProvider());

+ 8 - 0
app/src/main/res/drawable/ic_autorenew.xml

@@ -0,0 +1,8 @@
+<!-- drawable/autorenew.xml -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M12,6V9L16,5L12,1V4A8,8 0 0,0 4,12C4,13.57 4.46,15.03 5.24,16.26L6.7,14.8C6.25,13.97 6,13 6,12A6,6 0 0,1 12,6M18.76,7.74L17.3,9.2C17.74,10.04 18,11 18,12A6,6 0 0,1 12,18V15L8,19L12,23V20A8,8 0 0,0 20,12C20,10.43 19.54,8.97 18.76,7.74Z" />
+</vector>

+ 65 - 2
app/src/main/res/layout/activity_take_picture.xml

@@ -34,6 +34,13 @@
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
         android:layout_height="match_parent" />
 
 
+    <ImageView
+        android:id="@+id/photo_preview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:contentDescription="@null"
+        android:visibility="gone" />
+
     <com.google.android.material.button.MaterialButton
     <com.google.android.material.button.MaterialButton
         android:id="@+id/toggle_torch"
         android:id="@+id/toggle_torch"
         style="@style/Widget.AppTheme.Button.IconButton"
         style="@style/Widget.AppTheme.Button.IconButton"
@@ -41,8 +48,8 @@
         android:layout_height="48dp"
         android:layout_height="48dp"
         android:layout_alignParentTop="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentEnd="true"
         android:layout_alignParentEnd="true"
-        android:layout_marginTop="12dp"
         android:layout_marginStart="0dp"
         android:layout_marginStart="0dp"
+        android:layout_marginTop="12dp"
         android:layout_marginEnd="12dp"
         android:layout_marginEnd="12dp"
         android:contentDescription="@string/take_photo_toggle_torch"
         android:contentDescription="@string/take_photo_toggle_torch"
         android:insetLeft="4dp"
         android:insetLeft="4dp"
@@ -68,9 +75,9 @@
         android:layout_height="48dp"
         android:layout_height="48dp"
         android:layout_alignParentTop="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentEnd="true"
         android:layout_alignParentEnd="true"
+        android:layout_marginStart="12dp"
         android:layout_marginTop="12dp"
         android:layout_marginTop="12dp"
         android:layout_marginEnd="8dp"
         android:layout_marginEnd="8dp"
-        android:layout_marginStart="12dp"
         android:contentDescription="@string/take_photo_switch_camera"
         android:contentDescription="@string/take_photo_switch_camera"
         android:insetLeft="4dp"
         android:insetLeft="4dp"
         android:insetTop="4dp"
         android:insetTop="4dp"
@@ -89,6 +96,34 @@
         app:layout_constraintEnd_toStartOf="@+id/toggle_torch"
         app:layout_constraintEnd_toStartOf="@+id/toggle_torch"
         app:layout_constraintTop_toTopOf="parent" />
         app:layout_constraintTop_toTopOf="parent" />
 
 
+    <com.google.android.material.button.MaterialButton
+        android:id="@+id/retake"
+        style="@style/Widget.AppTheme.Button.IconButton"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentEnd="true"
+        android:layout_marginBottom="12dp"
+        android:contentDescription="@string/take_photo_switch_camera"
+        android:insetLeft="0dp"
+        android:insetTop="0dp"
+        android:insetRight="0dp"
+        android:insetBottom="0dp"
+        android:padding="0dp"
+        android:tint="@android:color/white"
+        android:visibility="gone"
+        app:backgroundTint="@color/colorPrimary"
+        app:cornerRadius="@dimen/button_corner_radius"
+        app:elevation="0dp"
+        app:icon="@drawable/ic_autorenew"
+        app:iconGravity="textStart"
+        app:iconPadding="0dp"
+        app:iconSize="24dp"
+        app:iconTint="@color/white"
+        app:layout_constraintBottom_toBottomOf="@id/takePhoto"
+        app:layout_constraintEnd_toStartOf="@id/takePhoto"
+        app:layout_constraintStart_toStartOf="parent" />
+
     <com.google.android.material.floatingactionbutton.FloatingActionButton
     <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/takePhoto"
         android:id="@+id/takePhoto"
         android:layout_width="wrap_content"
         android:layout_width="wrap_content"
@@ -103,4 +138,32 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:srcCompat="@drawable/ic_baseline_photo_camera_24" />
         app:srcCompat="@drawable/ic_baseline_photo_camera_24" />
+
+    <com.google.android.material.button.MaterialButton
+        android:id="@+id/send"
+        style="@style/Widget.AppTheme.Button.IconButton"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentEnd="true"
+        android:layout_marginBottom="12dp"
+        android:contentDescription="@string/take_photo_switch_camera"
+        android:insetLeft="0dp"
+        android:insetTop="0dp"
+        android:insetRight="0dp"
+        android:insetBottom="0dp"
+        android:padding="0dp"
+        android:tint="@android:color/white"
+        android:visibility="gone"
+        app:backgroundTint="@color/colorPrimary"
+        app:cornerRadius="@dimen/button_corner_radius"
+        app:elevation="0dp"
+        app:icon="@drawable/ic_send"
+        app:iconGravity="textStart"
+        app:iconPadding="0dp"
+        app:iconSize="24dp"
+        app:iconTint="@color/white"
+        app:layout_constraintBottom_toBottomOf="@id/takePhoto"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/takePhoto" />
 </androidx.constraintlayout.widget.ConstraintLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>