Skip to content

Commit 11de640

Browse files
authored
[CameraX • Compose] Migrate CameraXBasic Samples to Compose (#295)
1 parent a75d875 commit 11de640

File tree

10 files changed

+664
-19
lines changed

10 files changed

+664
-19
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ dependencies {
7474
implementation(project(":shared"))
7575
implementation(project(":samples:accessibility"))
7676
implementation(project(":samples:camera:camera2"))
77+
implementation(project(":samples:camera:camerax"))
7778
implementation(project(":samples:connectivity:audio"))
7879
implementation(project(":samples:connectivity:bluetooth:ble"))
7980
implementation(project(":samples:connectivity:bluetooth:companion"))

app/src/main/java/com/example/platform/app/ApiSurface.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ val CameraCamera2ApiSurface = ApiSurface(
3333
null,
3434
)
3535

36+
val CameraCameraXApiSurface = ApiSurface(
37+
"camera-camerax",
38+
"CameraX",
39+
null,
40+
)
41+
3642
val ConnectivityAudioApiSurface = ApiSurface(
3743
"connectivity-audio",
3844
"Connectivity Audio",
@@ -192,6 +198,7 @@ val UserInterfaceWindowManagerApiSurface = ApiSurface(
192198
val API_SURFACES = listOf(
193199
AccessiblityApiSurface,
194200
CameraCamera2ApiSurface,
201+
CameraCameraXApiSurface,
195202
ConnectivityAudioApiSurface,
196203
ConnectivityBluetoothBleApiSurface,
197204
ConnectivityBluetoothCompanionApiSurface,

app/src/main/java/com/example/platform/app/SampleDemo.kt

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.example.platform.accessibility.SpeakableText
2727
import com.example.platform.camera.imagecapture.Camera2ImageCapture
2828
import com.example.platform.camera.imagecapture.Camera2UltraHDRCapture
2929
import com.example.platform.camera.preview.Camera2Preview
30+
import com.example.platform.camerax.basic.CameraXBasic
3031
import com.example.platform.connectivity.audio.AudioCommsSample
3132
import com.example.platform.connectivity.bluetooth.ble.BLEScanIntentSample
3233
import com.example.platform.connectivity.bluetooth.ble.ConnectGATTSample
@@ -217,6 +218,18 @@ val SAMPLE_DEMOS by lazy {
217218
tags = listOf("Camera2"),
218219
content = { AndroidFragment<Camera2Preview>() },
219220
),
221+
222+
// CameraX Samples
223+
ComposableSampleDemo(
224+
id = "camerax-basic",
225+
name = "CameraX • Basic Image Capture",
226+
description = "This sample demonstrates how to capture an image & tap-to-focus using CameraX",
227+
documentation = "https://developer.android.com/training/camerax",
228+
apiSurface = CameraCameraXApiSurface,
229+
tags = listOf("CameraX"),
230+
content = { CameraXBasic() },
231+
),
232+
220233
ComposableSampleDemo(
221234
id = "communication-audio-manager",
222235
name = "Communication Audio Manager",
@@ -956,7 +969,7 @@ val SAMPLE_DEMOS by lazy {
956969
documentation = "https://source.android.com/docs/core/interaction/haptics",
957970
apiSurface = UserInterfaceHapticsApiSurface,
958971
tags = listOf("Haptics"),
959-
content = { HapticsBasic() }
972+
content = { HapticsBasic() },
960973
),
961974
ComposableSampleDemo(
962975
id = "haptics-2-resist",
@@ -965,7 +978,7 @@ val SAMPLE_DEMOS by lazy {
965978
documentation = "https://source.android.com/docs/core/interaction/haptics",
966979
apiSurface = UserInterfaceHapticsApiSurface,
967980
tags = listOf("Haptics"),
968-
content = { Resist() }
981+
content = { Resist() },
969982
),
970983
ComposableSampleDemo(
971984
id = "haptics-3-expand",
@@ -974,7 +987,7 @@ val SAMPLE_DEMOS by lazy {
974987
documentation = "https://source.android.com/docs/core/interaction/haptics",
975988
apiSurface = UserInterfaceHapticsApiSurface,
976989
tags = listOf("Haptics"),
977-
content = { Expand() }
990+
content = { Expand() },
978991
),
979992
ComposableSampleDemo(
980993
id = "haptics-4-bounce",
@@ -983,7 +996,7 @@ val SAMPLE_DEMOS by lazy {
983996
documentation = "https://source.android.com/docs/core/interaction/haptics",
984997
apiSurface = UserInterfaceHapticsApiSurface,
985998
tags = listOf("Haptics"),
986-
content = { Bounce() }
999+
content = { Bounce() },
9871000
),
9881001
ComposableSampleDemo(
9891002
id = "haptics-5-wobble",
@@ -992,7 +1005,7 @@ val SAMPLE_DEMOS by lazy {
9921005
documentation = "https://source.android.com/docs/core/interaction/haptics",
9931006
apiSurface = UserInterfaceHapticsApiSurface,
9941007
tags = listOf("Haptics"),
995-
content = { Wobble() }
1008+
content = { Wobble() },
9961009
),
9971010
ComposableSampleDemo(
9981011
id = "live-updates",
@@ -1014,23 +1027,23 @@ val SAMPLE_DEMOS by lazy {
10141027
description = "Basic usage of Picture-in-Picture mode showcasing video playback",
10151028
documentation = "https://developer.android.com/develop/ui/views/picture-in-picture",
10161029
apiSurface = UserInterfacePictureInPictureApiSurface,
1017-
content = PiPMovieActivity::class.java
1030+
content = PiPMovieActivity::class.java,
10181031
),
10191032
ActivitySampleDemo(
10201033
id = "picture-in-picture-stopwatch",
10211034
name = "Picture in Picture (PiP) - Stopwatch",
10221035
description = "Basic usage of Picture-in-Picture mode showcasing a stopwatch",
10231036
documentation = "https://developer.android.com/develop/ui/views/picture-in-picture",
10241037
apiSurface = UserInterfacePictureInPictureApiSurface,
1025-
content = PiPSampleActivity::class.java
1038+
content = PiPSampleActivity::class.java,
10261039
),
10271040
ActivitySampleDemo(
10281041
id = "predictive-back",
10291042
name = "Predictive Back",
10301043
description = "Shows Predictive Back animations.",
10311044
documentation = "https://developer.android.com/about/versions/14/features/predictive-back",
10321045
apiSurface = UserInterfacePredictiveBackApiSurface,
1033-
content = PBHostingActivity::class.java
1046+
content = PBHostingActivity::class.java,
10341047
),
10351048
ComposableSampleDemo(
10361049
id = "quick-settings",
@@ -1051,15 +1064,15 @@ val SAMPLE_DEMOS by lazy {
10511064
description = "Receive texts and images from other apps.",
10521065
documentation = null,
10531066
apiSurface = UserInterfaceShareApiSurface,
1054-
content = ShareReceiverActivity::class.java
1067+
content = ShareReceiverActivity::class.java,
10551068
),
10561069
ComposableSampleDemo(
10571070
id = "send-data-with-sharesheet",
10581071
name = "Send data with sharesheet",
10591072
description = "Send texts and images to other apps using the Android Sharesheet.",
10601073
documentation = null,
10611074
apiSurface = UserInterfaceShareApiSurface,
1062-
content = { ShareSender() }
1075+
content = { ShareSender() },
10631076
),
10641077
ComposableSampleDemo(
10651078
id = "conversion-suggestions",
@@ -1068,7 +1081,7 @@ val SAMPLE_DEMOS by lazy {
10681081
documentation = "https://developer.android.com/about/versions/13/features#text-conversion",
10691082
apiSurface = UserInterfaceTextApiSurface,
10701083
tags = listOf("Text"),
1071-
content = { AndroidFragment<ConversionSuggestions>() }
1084+
content = { AndroidFragment<ConversionSuggestions>() },
10721085
),
10731086
ComposableSampleDemo(
10741087
id = "downloadable-fonts",
@@ -1077,7 +1090,7 @@ val SAMPLE_DEMOS by lazy {
10771090
documentation = "https://developer.android.com/develop/ui/views/text-and-emoji/downloadable-fonts",
10781091
apiSurface = UserInterfaceTextApiSurface,
10791092
tags = listOf("Text"),
1080-
content = { AndroidFragment<DownloadableFontsFragment>() }
1093+
content = { AndroidFragment<DownloadableFontsFragment>() },
10811094
),
10821095
ComposableSampleDemo(
10831096
id = "hyphenation",
@@ -1086,7 +1099,7 @@ val SAMPLE_DEMOS by lazy {
10861099
documentation = "https://developer.android.com/reference/android/widget/TextView#attr_android:hyphenationFrequency",
10871100
apiSurface = UserInterfaceTextApiSurface,
10881101
tags = listOf("Text"),
1089-
content = { AndroidFragment<Hyphenation>() }
1102+
content = { AndroidFragment<Hyphenation>() },
10901103
),
10911104
ComposableSampleDemo(
10921105
id = "line-break",
@@ -1095,7 +1108,7 @@ val SAMPLE_DEMOS by lazy {
10951108
documentation = "https://developer.android.com/about/versions/13/features#japanese-wrapping",
10961109
apiSurface = UserInterfaceTextApiSurface,
10971110
tags = listOf("Text"),
1098-
content = { AndroidFragment<LineBreak>() }
1111+
content = { AndroidFragment<LineBreak>() },
10991112
),
11001113
ComposableSampleDemo(
11011114
id = "linkify",
@@ -1104,7 +1117,7 @@ val SAMPLE_DEMOS by lazy {
11041117
documentation = "https://developer.android.com/reference/kotlin/androidx/core/text/util/LinkifyCompat",
11051118
apiSurface = UserInterfaceTextApiSurface,
11061119
tags = listOf("Text"),
1107-
content = { AndroidFragment<Linkify>() }
1120+
content = { AndroidFragment<Linkify>() },
11081121
),
11091122
ComposableSampleDemo(
11101123
id = "text-span",
@@ -1113,31 +1126,31 @@ val SAMPLE_DEMOS by lazy {
11131126
documentation = "https://developer.android.com/kotlin/ktx#core",
11141127
apiSurface = UserInterfaceTextApiSurface,
11151128
tags = listOf("Text"),
1116-
content = { AndroidFragment<TextSpanFragment>() }
1129+
content = { AndroidFragment<TextSpanFragment>() },
11171130
),
11181131
ComposableSampleDemo(
11191132
id = "immersive-mode",
11201133
name = "Immersive mode",
11211134
description = "Immersive mode enables your app to display full-screen by hiding system bars.",
11221135
documentation = "https://developer.android.com/develop/ui/views/layout/immersive",
11231136
apiSurface = UserInterfaceWindowInsetsApiSurface,
1124-
content = { ImmersiveMode() }
1137+
content = { ImmersiveMode() },
11251138
),
11261139
ActivitySampleDemo(
11271140
id = "window-insets-animation",
11281141
name = "WindowInsetsAnimation",
11291142
description = "Shows how to react to the on-screen keyboard (IME) changing visibility, and also controlling the IME's visibility.",
11301143
documentation = "https://developer.android.com/develop/ui/views/layout/sw-keyboard",
11311144
apiSurface = UserInterfaceWindowInsetsApiSurface,
1132-
content = WindowInsetsAnimationActivity::class.java
1145+
content = WindowInsetsAnimationActivity::class.java,
11331146
),
11341147
ActivitySampleDemo(
11351148
id = "window-manager",
11361149
name = "WindowManager",
11371150
description = "Demonstrates how to use the Jetpack WindowManager library.",
11381151
documentation = "https://developer.android.com/jetpack/androidx/releases/window",
11391152
apiSurface = UserInterfaceWindowManagerApiSurface,
1140-
content = WindowDemosActivity::class.java
1153+
content = WindowDemosActivity::class.java,
11411154
),
11421155
).associateBy { it.id }
11431156
}

gradle/libs.versions.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ androidxTestExtTruth = "1.5.0"
5151
androidxTestRules = "1.5.0"
5252
androidxTestRunner = "1.5.2"
5353
androidxUiAutomator = "2.2.0"
54+
camerax = "1.5.0-beta01"
5455
material3Android = "1.3.2"
5556
media3 = "1.5.0"
5657
constraintlayout = "2.1.4"
@@ -59,6 +60,8 @@ glance = "1.1.0"
5960
tensorflowLite = "2.9.0"
6061
tensorflowLiteGpuDelegatePlugin = "0.4.4"
6162
tensorflowLiteSupport = "0.4.2"
63+
barcodeScanningCommon = "17.0.0"
64+
playServicesMlkitBarcodeScanning = "18.3.1"
6265

6366
[libraries]
6467
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -170,6 +173,16 @@ androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", versi
170173
androidx-media3-transformer = { module = "androidx.media3:media3-transformer", version.ref = "media3" }
171174
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3" }
172175

176+
# CameraX
177+
androidx-camerax-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }
178+
androidx-camerax-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }
179+
androidx-camerax-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }
180+
androidx-camerax-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camerax" }
181+
androidx-camerax-video = { module = "androidx.camera:camera-video", version.ref = "camerax" }
182+
androidx-camerax-view = { module = "androidx.camera:camera-view", version.ref = "camerax" }
183+
androidx-camerax-mlkit-vision = { module = "androidx.camera:camera-mlkit-vision", version.ref = "camerax" }
184+
androidx-camerax-extensions = { module = "androidx.camera:camera-extensions", version.ref = "camerax" }
185+
173186
fresco = "com.facebook.fresco:fresco:3.0.0"
174187
fresco-nativeimagetranscoder = "com.facebook.fresco:nativeimagetranscoder:2.6.0!!"
175188
glide = "com.github.bumptech.glide:glide:4.15.1"
@@ -181,6 +194,8 @@ tensorflow-lite-gpu = { module = "org.tensorflow:tensorflow-lite-gpu", version.r
181194
tensorflow-lite-gpu-delegate-plugin = { module = "org.tensorflow:tensorflow-lite-gpu-delegate-plugin", version.ref = "tensorflowLiteGpuDelegatePlugin" }
182195
tensorflow-lite-select-tf-ops = { module = "org.tensorflow:tensorflow-lite-select-tf-ops", version.ref = "tensorflowLite" }
183196
tensorflow-lite-support = { module = "org.tensorflow:tensorflow-lite-support", version.ref = "tensorflowLiteSupport" }
197+
barcode-scanning-common = { group = "com.google.mlkit", name = "barcode-scanning-common", version.ref = "barcodeScanningCommon" }
198+
play-services-mlkit-barcode-scanning = { group = "com.google.android.gms", name = "play-services-mlkit-barcode-scanning", version.ref = "playServicesMlkitBarcodeScanning" }
184199

185200
[plugins]
186201
android-application = { id = "com.android.application", version.ref = "agp" }

samples/camera/camerax/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TBD
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
plugins {
18+
alias(libs.plugins.android.library)
19+
alias(libs.plugins.kotlin.compose)
20+
alias(libs.plugins.kotlin.android)
21+
}
22+
23+
android {
24+
namespace = "com.example.platform.camerax"
25+
compileSdk = 35
26+
27+
defaultConfig {
28+
minSdk = 21
29+
testOptions.targetSdk = 35
30+
}
31+
kotlinOptions {
32+
jvmTarget = "1.8"
33+
}
34+
}
35+
36+
dependencies {
37+
implementation(platform(libs.androidx.compose.bom))
38+
implementation(libs.androidx.ui)
39+
implementation(libs.androidx.ui.graphics)
40+
implementation(libs.androidx.ui.tooling.preview)
41+
implementation(libs.androidx.lifecycle.viewmodel.compose)
42+
implementation(libs.androidx.material3)
43+
implementation(project(":shared"))
44+
45+
// CameraX
46+
implementation(libs.androidx.camerax.core)
47+
implementation(libs.androidx.camerax.camera2)
48+
implementation(libs.androidx.camerax.compose)
49+
implementation(libs.androidx.camerax.extensions)
50+
implementation(libs.androidx.camerax.lifecycle)
51+
implementation(libs.androidx.camerax.mlkit.vision)
52+
implementation(libs.androidx.camerax.video)
53+
implementation(libs.androidx.camerax.view)
54+
55+
// Image loading
56+
implementation(libs.coil)
57+
implementation(libs.coil.compose)
58+
59+
// Barcode Scanning
60+
implementation(libs.barcode.scanning.common)
61+
implementation(libs.play.services.mlkit.barcode.scanning)
62+
63+
// Permissions
64+
implementation(libs.accompanist.permissions)
65+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright 2023 The Android Open Source Project
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ https://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<uses-permission android:name="android.permission.CAMERA" />
20+
<uses-permission
21+
android:name="android.permission.READ_EXTERNAL_STORAGE"
22+
android:maxSdkVersion="32" />
23+
<uses-permission
24+
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
25+
android:maxSdkVersion="28" />
26+
<uses-feature
27+
android:name="android.hardware.camera"
28+
android:required="false" />
29+
30+
<application>
31+
32+
<!-- Register file provider to create shareable URIs -->
33+
<provider
34+
android:name="androidx.core.content.FileProvider"
35+
android:authorities="${applicationId}.provider"
36+
android:exported="false"
37+
android:grantUriPermissions="true">
38+
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" />
39+
</provider>
40+
</application>
41+
</manifest>

0 commit comments

Comments
 (0)