diff --git a/app/build.gradle b/app/build.gradle
index 260c533..bee2cf8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -34,15 +34,15 @@ android {
}
dependencies {
- implementation 'androidx.camera:camera-view:1.3.1'
- implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.11.0'
- implementation 'androidx.camera:camera-lifecycle:1.3.1'
- implementation "androidx.camera:camera-camera2:1.3.1"
- implementation 'com.google.android.material:material:1.11.0'
- implementation 'androidx.compose.material3:material3:1.1.2'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.camera:camera-view:1.4.1'
+ implementation 'androidx.appcompat:appcompat:1.7.0'
+ implementation 'com.google.android.material:material:1.12.0'
+ implementation 'androidx.camera:camera-lifecycle:1.4.1'
+ implementation 'androidx.camera:camera-camera2:1.4.1'
+ implementation 'com.google.android.material:material:1.12.0'
+ implementation 'androidx.compose.material3:material3:1.3.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.5'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+ androidTestImplementation 'androidx.test.ext:junit:1.2.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
}
\ No newline at end of file
diff --git a/app/src/main/java/com/polar/mirror/FreezeController.java b/app/src/main/java/com/polar/mirror/FreezeController.java
index d059df5..9509b21 100644
--- a/app/src/main/java/com/polar/mirror/FreezeController.java
+++ b/app/src/main/java/com/polar/mirror/FreezeController.java
@@ -38,6 +38,7 @@ public class FreezeController {
private final Context mContext;
private boolean mCameraFrozen = false;
private final FloatingActionButton mFreezeButton;
+ private int selectedCamera = CameraSelector.LENS_FACING_FRONT;
FreezeController(Context context, FloatingActionButton freezeButton, PreviewView cameraView,
ImageView freezeView){
@@ -57,25 +58,27 @@ public class FreezeController {
*/
public void onCameraInitialized(@NonNull ProcessCameraProvider provider, LifecycleOwner lcOwner){
CameraSelector cameraSelector = new CameraSelector.Builder()
- .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
+ .requireLensFacing(selectedCamera)
.build();
provider.bindToLifecycle(lcOwner, cameraSelector, mImageCapture);
Log.d(TAG, "completed onCameraInitialized");
}
private int getRotationAngleFromOrientation(int orientation){
- int angle = 270;
+ int angle;
+ boolean rearCamera = getSelectedCamera() == CameraSelector.LENS_FACING_BACK;
switch (orientation) {
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
- angle = 90;
+ angle = rearCamera ? 270 : 90;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
+ angle = rearCamera ? 90 : 270;
break;
}
return angle;
@@ -151,4 +154,17 @@ public void toggleFreeze(){
mCameraFrozen = true;
}
}
+
+ public void toggleSelectedCamera() {
+ if (selectedCamera == CameraSelector.LENS_FACING_FRONT) {
+ selectedCamera = CameraSelector.LENS_FACING_BACK;
+ } else {
+ selectedCamera = CameraSelector.LENS_FACING_FRONT;
+ }
+ }
+
+ public int getSelectedCamera() {
+ return selectedCamera;
+ }
+
}
diff --git a/app/src/main/java/com/polar/mirror/MainActivity.java b/app/src/main/java/com/polar/mirror/MainActivity.java
index a40593f..784ec0e 100644
--- a/app/src/main/java/com/polar/mirror/MainActivity.java
+++ b/app/src/main/java/com/polar/mirror/MainActivity.java
@@ -4,6 +4,7 @@
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
+import androidx.camera.core.MirrorMode;
import androidx.camera.core.Preview;
import androidx.camera.view.PreviewView;
import androidx.camera.lifecycle.ProcessCameraProvider;
@@ -14,6 +15,7 @@
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
+import android.view.Surface;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
@@ -33,6 +35,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private final static String TAG = "MainActivity";
private Preview mPreview = null;
private static final int CAMERA_PERMISSION_CODE = 858;
+ private ProcessCameraProvider mCameraProvider = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -125,12 +128,15 @@ private void setupFloatingButtons(){
FloatingActionButton exitButton = findViewById(R.id.exit_button);
FloatingActionButton freezeButton = findViewById(R.id.freeze_button);
FloatingActionButton lowLightButton = findViewById(R.id.low_light_button);
+ FloatingActionButton cameraChooserButton = findViewById(R.id.camera_chooser_button);
exitButton.setClickable(true);
exitButton.setOnClickListener(this);
freezeButton.setClickable(true);
freezeButton.setOnClickListener(this);
lowLightButton.setClickable(true);
lowLightButton.setOnClickListener(this);
+ cameraChooserButton.setClickable(true);
+ cameraChooserButton.setOnClickListener(this);
}
/**
@@ -147,17 +153,22 @@ private void hideSystemUi(){
* @throws ExecutionException in case of task errors
* @throws InterruptedException in case of thread interruption
*/
+ @androidx.annotation.OptIn(markerClass = androidx.camera.core.ExperimentalMirrorMode.class)
private void startCamera() throws ExecutionException, InterruptedException {
- mPreview = new Preview.Builder().build();
+ mCameraView.setImplementationMode(PreviewView.ImplementationMode.COMPATIBLE);
+ mCameraView.addOnLayoutChangeListener(this::onLayoutChange);
+ mPreview = new Preview.Builder()
+ .setMirrorMode(MirrorMode.MIRROR_MODE_ON)
+ .build();
mPreview.setSurfaceProvider(mCameraView.getSurfaceProvider());
- ProcessCameraProvider cameraProvider = ProcessCameraProvider.getInstance(this).get();
+ mCameraProvider = ProcessCameraProvider.getInstance(this).get();
try {
CameraSelector cameraSelector = new CameraSelector.Builder()
- .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
+ .requireLensFacing(mFreezeController.getSelectedCamera())
.build();
- cameraProvider.unbindAll();
- cameraProvider.bindToLifecycle(this, cameraSelector, mPreview);
- mFreezeController.onCameraInitialized(cameraProvider, this);
+ mCameraProvider.unbindAll();
+ mCameraProvider.bindToLifecycle(this, cameraSelector, mPreview);
+ mFreezeController.onCameraInitialized(mCameraProvider, this);
} catch (Exception e) {
e.printStackTrace();
}
@@ -178,6 +189,19 @@ private void toggleLowLightMode(){
mLowLightController.toggleLowLightMode();
}
+ /**
+ * Toggles front/rear camera
+ */
+ private void toggleSelectedCamera(){
+ mFreezeController.toggleSelectedCamera();
+ CameraSelector cameraSelector = new CameraSelector.Builder()
+ .requireLensFacing(mFreezeController.getSelectedCamera())
+ .build();
+ mCameraProvider.unbindAll();
+ mCameraProvider.bindToLifecycle(this, cameraSelector, mPreview);
+ mFreezeController.onCameraInitialized(mCameraProvider, this);
+ }
+
@Override
public void onClick(@NonNull View v) {
int viewId = v.getId();
@@ -188,6 +212,8 @@ public void onClick(@NonNull View v) {
toggleCameraFreeze();
} else if(viewId == R.id.low_light_button){
toggleLowLightMode();
+ } else if(viewId == R.id.camera_chooser_button){
+ toggleSelectedCamera();
} else {
Log.w(TAG, "Unknown id of view: " + viewId);
}
@@ -218,5 +244,28 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
}
}
}
-}
+ private void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
+ int orientation = mCameraView.getDisplay().getRotation();
+ if (mFreezeController.getSelectedCamera() == CameraSelector.LENS_FACING_BACK) {
+ int o;
+ switch (orientation) {
+ case Surface.ROTATION_0:
+ o = Surface.ROTATION_0;
+ break;
+ case Surface.ROTATION_90:
+ o = Surface.ROTATION_270;
+ break;
+ case Surface.ROTATION_180:
+ o = Surface.ROTATION_180;
+ break;
+ default: // Surface.ROTATION_270:
+ o = Surface.ROTATION_90;
+ break;
+ }
+ mPreview.setTargetRotation(o);
+ } else {
+ mPreview.setTargetRotation(orientation);
+ }
+ }
+}
diff --git a/app/src/main/res/layout/action_panel.xml b/app/src/main/res/layout/action_panel.xml
index 3e70c76..fc08ded 100644
--- a/app/src/main/res/layout/action_panel.xml
+++ b/app/src/main/res/layout/action_panel.xml
@@ -85,6 +85,30 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 76f4cc3..597697e 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -9,4 +9,5 @@
Dostęp do kamery nie został przyznany. Użyj aplikacji Ustawienia, aby pryznać dostęp
Tryb ciemności
Overlay trybu ciemności
+ Obrót
\ No newline at end of file
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 8f7e655..09f7bbd 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -8,4 +8,5 @@
Доступ до камери не надано. Скористуйтесь застосунком Налаштування, аби надати доступ вручну
Режим пітьми
Оверлей режим пітьми
+ Фліп
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8c2affd..49e228f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,4 +8,5 @@
Camera permissions was not granted. Use Settings app to grant it.
Dark mode
Low light mode overlay
+ Flip
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 11bab8c..f1187a3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,4 +1,4 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
-id 'com.android.application' version '8.3.1' apply false
+id 'com.android.application' version '8.7.3' apply false
}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 828358b..a2e5fd7 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,11 @@
#Tue Oct 24 12:02:08 CEST 2023
+# suppress inspection "Annotator"
distributionBase=GRADLE_USER_HOME
+# suppress inspection "Annotator"
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+# suppress inspection "Annotator"
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
+# suppress inspection "Annotator"
zipStoreBase=GRADLE_USER_HOME
+# suppress inspection "Annotator"
zipStorePath=wrapper/dists