diff --git a/app/Android.bp b/app/Android.bp index a3f3a7060d63d1d0e0b687e2d0a0531ee5ff8e13..61f8f33a046c3e80ccea65bddfeccb77cc419f78 100644 --- a/app/Android.bp +++ b/app/Android.bp @@ -37,6 +37,9 @@ android_app { optional_uses_libs: [ "androidx.camera.extensions.impl" ], + required: [ + "ApertureLensLauncher", + ], optimize: { proguard_flags_files: ["proguard-rules.pro"], diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 90e8a96719e6cc0d7930ee5f5a6817e4dba77f96..0c17bcc1138abfee42382fbc0bbe20430d4a5e55 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,6 +20,8 @@ android:maxSdkVersion="28" /> <queries> + <package android:name="com.google.android.apps.googlecamera.fishfood" /> + <package android:name="com.google.android.googlequicksearchbox" /> <package android:name="org.lineageos.aperture.auto_generated_rro_product__" /> <package android:name="org.lineageos.aperture.auto_generated_rro_vendor__" /> </queries> diff --git a/app/src/main/java/org/lineageos/aperture/CameraActivity.kt b/app/src/main/java/org/lineageos/aperture/CameraActivity.kt index d357871f468e1fb25dab0d55f24d5efb0c78de54..b8eab990385cae0a5591a4e7b5c41d49b80a17aa 100644 --- a/app/src/main/java/org/lineageos/aperture/CameraActivity.kt +++ b/app/src/main/java/org/lineageos/aperture/CameraActivity.kt @@ -55,6 +55,7 @@ import androidx.camera.view.onPinchToZoom import androidx.camera.view.video.AudioConfig import androidx.cardview.widget.CardView import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.Group import androidx.core.content.ContextCompat import androidx.core.view.WindowCompat.getInsetsController import androidx.core.view.WindowInsetsCompat @@ -90,6 +91,7 @@ import org.lineageos.aperture.utils.CameraSoundsUtils import org.lineageos.aperture.utils.CameraState import org.lineageos.aperture.utils.FlashMode import org.lineageos.aperture.utils.Framerate +import org.lineageos.aperture.utils.GoogleLensUtils import org.lineageos.aperture.utils.GridMode import org.lineageos.aperture.utils.MediaType import org.lineageos.aperture.utils.PermissionsUtils @@ -120,6 +122,7 @@ open class CameraActivity : AppCompatActivity() { private val flipCameraButton by lazy { findViewById<ImageButton>(R.id.flipCameraButton) } private val galleryButton by lazy { findViewById<ImageView>(R.id.galleryButton) } private val galleryButtonCardView by lazy { findViewById<CardView>(R.id.galleryButtonCardView) } + private val googleLensButton by lazy { findViewById<ImageButton>(R.id.googleLensButton) } private val gridButton by lazy { findViewById<Button>(R.id.gridButton) } private val gridView by lazy { findViewById<GridView>(R.id.gridView) } private val lensSelectorLayout by lazy { findViewById<LensSelectorLayout>(R.id.lensSelectorLayout) } @@ -127,7 +130,7 @@ open class CameraActivity : AppCompatActivity() { private val micButton by lazy { findViewById<Button>(R.id.micButton) } private val photoModeButton by lazy { findViewById<MaterialButton>(R.id.photoModeButton) } private val previewBlurView by lazy { findViewById<PreviewBlurView>(R.id.previewBlurView) } - private val primaryBarLayout by lazy { findViewById<ConstraintLayout>(R.id.primaryBarLayout) } + private val primaryBarLayoutGroupPhoto by lazy { findViewById<Group>(R.id.primaryBarLayoutGroupPhoto) } private val proButton by lazy { findViewById<ImageButton>(R.id.proButton) } private val qrModeButton by lazy { findViewById<MaterialButton>(R.id.qrModeButton) } private val secondaryBottomBarLayout by lazy { findViewById<ConstraintLayout>(R.id.secondaryBottomBarLayout) } @@ -195,6 +198,7 @@ open class CameraActivity : AppCompatActivity() { // QR private val imageAnalyzer by lazy { QrImageAnalyzer(this) } + private val isGoogleLensAvailable by lazy { GoogleLensUtils.isGoogleLensAvailable(this) } private var viewFinderTouchEvent: MotionEvent? = null private val gestureDetector by lazy { @@ -635,6 +639,11 @@ open class CameraActivity : AppCompatActivity() { videoModeButton.setOnClickListener { changeCameraMode(CameraMode.VIDEO) } flipCameraButton.setOnClickListener { flipCamera() } + googleLensButton.setOnClickListener { + dismissKeyguardAndRun { + GoogleLensUtils.launchGoogleLens(this) + } + } videoRecordingStateButton.setOnClickListener { when (cameraState) { @@ -1050,17 +1059,20 @@ open class CameraActivity : AppCompatActivity() { CameraMode.QR -> { timerButton.isVisible = false secondaryBottomBarLayout.isVisible = false - primaryBarLayout.isVisible = false + primaryBarLayoutGroupPhoto.isVisible = false + googleLensButton.isVisible = isGoogleLensAvailable } CameraMode.PHOTO -> { timerButton.isVisible = true secondaryBottomBarLayout.isVisible = true - primaryBarLayout.isVisible = true + primaryBarLayoutGroupPhoto.isVisible = true + googleLensButton.isVisible = false } CameraMode.VIDEO -> { timerButton.isVisible = true secondaryBottomBarLayout.isVisible = true - primaryBarLayout.isVisible = true + primaryBarLayoutGroupPhoto.isVisible = true + googleLensButton.isVisible = false } } diff --git a/app/src/main/java/org/lineageos/aperture/utils/GoogleLensUtils.kt b/app/src/main/java/org/lineageos/aperture/utils/GoogleLensUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..8727c0b368b1ba48b7c7fad180965ddc473bc8f5 --- /dev/null +++ b/app/src/main/java/org/lineageos/aperture/utils/GoogleLensUtils.kt @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2023 The LineageOS Project + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.lineageos.aperture.utils + +import android.content.Context +import android.content.Intent + +object GoogleLensUtils { + private const val GSA_PACKAGE_NAME = "com.google.android.googlequicksearchbox" + private const val LAUNCHER_PACKAGE_NAME = "com.google.android.apps.googlecamera.fishfood" + + private fun isGsaAvailable(context: Context) = runCatching { + @Suppress("DEPRECATION") + context.packageManager.getApplicationInfo(GSA_PACKAGE_NAME, 0).enabled + }.getOrDefault(false) + + private fun isLensLauncherAvailable(context: Context) = runCatching { + @Suppress("DEPRECATION") + context.packageManager.getApplicationInfo(LAUNCHER_PACKAGE_NAME, 0).enabled + }.getOrDefault(false) + + fun isGoogleLensAvailable(context: Context) = + isGsaAvailable(context) && isLensLauncherAvailable(context) + + fun launchGoogleLens(context: Context) { + context.startActivity( + Intent().setClassName(LAUNCHER_PACKAGE_NAME, "$LAUNCHER_PACKAGE_NAME.MainActivity") + ) + } +} diff --git a/app/src/main/res/drawable/ic_google_lens.xml b/app/src/main/res/drawable/ic_google_lens.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2bb1b1be04e10a1edb8fc92ad36d15cfee3a346 --- /dev/null +++ b/app/src/main/res/drawable/ic_google_lens.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="512" + android:viewportHeight="512"> + <path + android:fillColor="@android:color/white" + android:pathData="M71.5,140.2c0,-37.9 30.8,-68.7 68.7,-68.7h58.7V0h-58.7C62.9,0 0,62.9 0,140.2v58.8h71.5V140.2z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M371.8,71.5c37.9,0 68.7,30.8 68.7,68.7v58.8H512v-58.8C512,62.9 449.1,0 371.8,0h-58.7v71.5H371.8z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M140.2,440.5c-37.9,0 -68.7,-30.8 -68.7,-68.7v-58.6H0v58.6C0,449.1 62.9,512 140.2,512h58.8v-71.5H140.2z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M256,256m-99.3,0a99.3,99.3 0,1 1,198.6 0a99.3,99.3 0,1 1,-198.6 0" /> + <path + android:fillColor="@android:color/white" + android:pathData="M483.5,427.2c0,31.3 -25.4,56.6 -56.6,56.6c-31.3,0 -56.6,-25.4 -56.6,-56.6c0,-31.3 25.4,-56.6 56.6,-56.6C458.1,370.6 483.5,396 483.5,427.2z" /> +</vector> diff --git a/app/src/main/res/layout/activity_camera.xml b/app/src/main/res/layout/activity_camera.xml index 801c59450c41c326c06ce082ce9f66cd4131e81a..a4e82aed36b75efa1a26d9f562b84ef79ad4cc7d 100644 --- a/app/src/main/res/layout/activity_camera.xml +++ b/app/src/main/res/layout/activity_camera.xml @@ -284,6 +284,12 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"> + <androidx.constraintlayout.widget.Group + android:id="@+id/primaryBarLayoutGroupPhoto" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:constraint_referenced_ids="galleryButtonCardView,shutterButton,flipCameraButton" /> + <ImageButton android:id="@+id/shutterButton" android:layout_width="75dp" @@ -318,6 +324,19 @@ android:scaleType="centerCrop" /> </androidx.cardview.widget.CardView> + <ImageButton + android:id="@+id/googleLensButton" + android:layout_width="60dp" + android:layout_height="60dp" + android:layout_marginStart="32dp" + android:background="@null" + android:contentDescription="@string/google_lens_button_description" + android:scaleType="center" + android:src="@drawable/ic_google_lens" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + <ImageButton android:id="@+id/flipCameraButton" android:layout_width="60dp" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ee28f1e1ab4098b458e2ebbf36bbd6bf6bb4bbee..c8a75edcc6f35a9a373420ee392695663c8eae10 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ <string name="flash_button_description">Flash mode</string> <string name="flip_camera_button_description">Flip camera</string> <string name="gallery_button_description">Gallery</string> + <string name="google_lens_button_description">Open Google Lens</string> <string name="image_view_description">Image preview</string> <string name="photo_mode_button_description">Switch to photo mode</string> <string name="pro_button_description">Pro settings</string> diff --git a/lens_launcher/.gitignore b/lens_launcher/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/lens_launcher/.gitignore @@ -0,0 +1 @@ +/build diff --git a/lens_launcher/Android.bp b/lens_launcher/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..4d805301d374b5745f5f83e55217e588f1d303aa --- /dev/null +++ b/lens_launcher/Android.bp @@ -0,0 +1,19 @@ +// +// Copyright (C) 2023 The LineageOS Project +// +// SPDX-License-Identifier: Apache-2.0 +// + +android_app { + name: "ApertureLensLauncher", + + srcs: ["src/main/java/**/*.kt"], + manifest: "src/main/AndroidManifest.xml", + + sdk_version: "current", + product_specific: true, + + optimize: { + proguard_flags_files: ["proguard-rules.pro"], + }, +} diff --git a/lens_launcher/build.gradle.kts b/lens_launcher/build.gradle.kts new file mode 100644 index 0000000000000000000000000000000000000000..46285ad647a8becd308a9b18146e93d6f0020f1d --- /dev/null +++ b/lens_launcher/build.gradle.kts @@ -0,0 +1,43 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + compileSdk = 33 + + defaultConfig { + applicationId = "com.google.android.apps.googlecamera.fishfood" + minSdk = 26 + targetSdk = 33 + versionCode = 1 + versionName = "1.0" + } + + buildTypes { + getByName("release") { + // Enables code shrinking, obfuscation, and optimization. + isMinifyEnabled = true + + // Enables resource shrinking. + isShrinkResources = true + + // Includes the default ProGuard rules files. + setProguardFiles( + listOf( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + ) + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + } +} diff --git a/lens_launcher/proguard-rules.pro b/lens_launcher/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..f1b424510da51fd82143bc74a0a801ae5a1e2fcd --- /dev/null +++ b/lens_launcher/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/lens_launcher/src/main/AndroidManifest.xml b/lens_launcher/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..ecb25de5afc650ed7d80212683b95feb449c4c33 --- /dev/null +++ b/lens_launcher/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + SPDX-FileCopyrightText: 2023 The LineageOS Project + SPDX-License-Identifier: Apache-2.0 +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.google.android.apps.googlecamera.fishfood"> + + <application + android:label="ApertureLensLauncher" + tools:ignore="MissingApplicationIcon"> + <activity + android:name=".MainActivity" + android:exported="true" + android:theme="@android:style/Theme.NoDisplay"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/lens_launcher/src/main/java/com/google/android/apps/googlecamera/fishfood/MainActivity.kt b/lens_launcher/src/main/java/com/google/android/apps/googlecamera/fishfood/MainActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..5f51ede1839bc1a8e6eed90e1030e4424131cbc6 --- /dev/null +++ b/lens_launcher/src/main/java/com/google/android/apps/googlecamera/fishfood/MainActivity.kt @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2023 The LineageOS Project + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.apps.googlecamera.fishfood + +import android.app.Activity +import android.content.Intent +import android.net.Uri +import android.os.Bundle + +class MainActivity : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + startActivityForResult( + Intent() + .setAction(Intent.ACTION_VIEW) + .setData(Uri.parse("googleapp://lens")) + .setPackage("com.google.android.googlequicksearchbox"), + 0 + ) + + finish() + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 0bf66b333883f59144b6bf466ef1f5c741d80b7e..5a39a70fc0b524aec08cba0a969bcdb0c6290c24 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,3 +15,4 @@ dependencyResolutionManagement { } rootProject.name = "Aperture" include(":app") +include(":lens_launcher")