1 /*
<lambda>null2 * Copyright (C) 2019 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 * http://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 package androidx.activity.integration.testapp
18
19 import android.Manifest.permission.ACCESS_FINE_LOCATION
20 import android.app.Activity
21 import android.app.PendingIntent
22 import android.content.Context
23 import android.content.Intent
24 import android.net.Uri
25 import android.os.Build
26 import android.os.Bundle
27 import android.provider.MediaStore
28 import android.view.View
29 import android.view.ViewGroup
30 import android.view.ViewGroup.LayoutParams.MATCH_PARENT
31 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
32 import android.view.ViewManager
33 import android.widget.Button
34 import android.widget.LinearLayout
35 import android.widget.LinearLayout.VERTICAL
36 import android.widget.Toast
37 import androidx.activity.ComponentActivity
38 import androidx.activity.result.ActivityResultLauncher
39 import androidx.activity.result.IntentSenderRequest
40 import androidx.activity.result.PickVisualMediaRequest
41 import androidx.activity.result.contract.ActivityResultContracts
42 import androidx.activity.result.contract.ActivityResultContracts.CaptureVideo
43 import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
44 import androidx.activity.result.contract.ActivityResultContracts.GetContent
45 import androidx.activity.result.contract.ActivityResultContracts.OpenMultipleDocuments
46 import androidx.activity.result.contract.ActivityResultContracts.PickMultipleVisualMedia
47 import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
48 import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.MediaCapabilities
49 import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
50 import androidx.activity.result.contract.ActivityResultContracts.TakePicture
51 import androidx.activity.result.contract.ActivityResultContracts.TakePicturePreview
52 import androidx.activity.result.launch
53 import androidx.activity.result.registerForActivityResult
54 import androidx.core.content.FileProvider
55 import java.io.File
56
57 class MainActivity : ComponentActivity() {
58
59 val requestLocation =
60 registerForActivityResult(RequestPermission(), ACCESS_FINE_LOCATION) { isGranted ->
61 toast("Location granted: $isGranted")
62 }
63
64 val takePicturePreview =
65 registerForActivityResult(TakePicturePreview()) { bitmap -> toast("Got picture: $bitmap") }
66
67 val takePicture =
68 registerForActivityResult(TakePicture()) { success -> toast("Got picture: $success") }
69
70 val captureVideo: ActivityResultLauncher<Uri> =
71 registerForActivityResult(CaptureVideo()) { success -> toast("Got video: $success") }
72
73 val getContent: ActivityResultLauncher<String> =
74 registerForActivityResult(GetContent()) { uri -> toast("Got image: $uri") }
75
76 lateinit var pickVisualMedia: ActivityResultLauncher<PickVisualMediaRequest>
77
78 lateinit var pickMultipleVisualMedia: ActivityResultLauncher<PickVisualMediaRequest>
79
80 lateinit var createDocument: ActivityResultLauncher<String>
81
82 lateinit var openDocuments: ActivityResultLauncher<Array<String>>
83
84 private val intentSender =
85 registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
86 toast("Received intent sender callback")
87 }
88
89 override fun onCreate(savedInstanceState: Bundle?) {
90 super.onCreate(savedInstanceState)
91
92 pickVisualMedia =
93 registerForActivityResult(PickVisualMedia()) { uri -> toast("Got image: $uri") }
94 pickMultipleVisualMedia =
95 registerForActivityResult(PickMultipleVisualMedia(5)) { uris ->
96 var media = ""
97 uris.forEach { media += "uri: $it \n" }
98 toast("Got media files: $media")
99 }
100 createDocument =
101 registerForActivityResult(CreateDocument("image/png")) { uri ->
102 toast("Created document: $uri")
103 }
104 openDocuments =
105 registerForActivityResult(OpenMultipleDocuments()) { uris ->
106 var docs = ""
107 uris.forEach { docs += "uri: $it \n" }
108 toast("Got documents: $docs")
109 }
110
111 setContentView {
112 add(::LinearLayout) {
113 orientation = VERTICAL
114
115 button("Request location permission") { requestLocation.launch() }
116 button("Get picture thumbnail") { takePicturePreview.launch() }
117 button("Take pic") {
118 val file = File(filesDir, "image")
119 val uri = FileProvider.getUriForFile(this@MainActivity, packageName, file)
120 takePicture.launch(uri)
121 }
122 button("Capture video") {
123 val file = File(filesDir, "video")
124 val uri = FileProvider.getUriForFile(this@MainActivity, packageName, file)
125 captureVideo.launch(uri)
126 }
127 button("Pick an image (w/ GET_CONTENT)") { getContent.launch("image/*") }
128 button("Pick an image (w/ photo picker)") {
129 pickVisualMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))
130 }
131 button("Pick a GIF (w/ photo picker)") {
132 pickVisualMedia.launch(
133 PickVisualMediaRequest(PickVisualMedia.SingleMimeType("image/gif"))
134 )
135 }
136 button("Pick an image & show albums tab (w/ photo picker)") {
137 pickVisualMedia.launch(
138 PickVisualMediaRequest(
139 mediaType = PickVisualMedia.ImageOnly,
140 defaultTab = PickVisualMedia.DefaultTab.AlbumsTab
141 )
142 )
143 }
144 button("Pick an image & green accent color (w/ photo picker)") {
145 pickVisualMedia.launch(
146 PickVisualMediaRequest(
147 mediaType = PickVisualMedia.ImageOnly,
148 accentColor = 0xFF123456
149 )
150 )
151 }
152 button("Pick 5 visual media max (w/ photo picker)") {
153 pickMultipleVisualMedia.launch(
154 PickVisualMediaRequest(PickVisualMedia.ImageAndVideo)
155 )
156 }
157 button("Pick 3 visual media max (w/ photo picker)") {
158 pickMultipleVisualMedia.launch(
159 PickVisualMediaRequest(
160 mediaType = PickVisualMedia.ImageAndVideo,
161 maxItems = 3
162 )
163 )
164 }
165 button("Pick 5 visual media max (w/ photo picker) & selection order") {
166 pickMultipleVisualMedia.launch(
167 PickVisualMediaRequest(isOrderedSelection = true)
168 )
169 }
170 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
171 button("Pick 5 videos max (w/ photo picker) & transcoding HDR to SDR") {
172 pickMultipleVisualMedia.launch(
173 PickVisualMediaRequest(
174 mediaType = PickVisualMedia.VideoOnly,
175 mediaCapabilitiesForTranscoding =
176 MediaCapabilities.Builder().build()
177 )
178 )
179 }
180 }
181 button("Create document") { createDocument.launch("Temp") }
182 button("Open documents") { openDocuments.launch(arrayOf("*/*")) }
183 button("Start IntentSender") {
184 val request =
185 IntentSenderRequest.Builder(
186 PendingIntent.getActivity(
187 context,
188 0,
189 Intent(MediaStore.ACTION_IMAGE_CAPTURE),
190 PendingIntent.FLAG_IMMUTABLE
191 )
192 )
193 .setFlags(
194 Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP,
195 1
196 )
197 .build()
198 intentSender.launch(request)
199 }
200 }
201 }
202 }
203 }
204
Contextnull205 fun Context.toast(msg: String) {
206 Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
207 }
208
setContentViewnull209 inline fun Activity.setContentView(ui: ViewManager.() -> Unit) = ActivityViewManager(this).apply(ui)
210
211 class ActivityViewManager(val activity: Activity) : ViewManager {
212 override fun addView(p0: View?, p1: ViewGroup.LayoutParams?) {
213 activity.setContentView(p0)
214 }
215
216 override fun updateViewLayout(p0: View?, p1: ViewGroup.LayoutParams?) {
217 TODO("not implemented")
218 }
219
220 override fun removeView(p0: View?) {
221 TODO("not implemented")
222 }
223 }
224
225 val ViewManager.context
226 get() =
227 when (this) {
228 is View -> context
229 is ActivityViewManager -> activity
230 else -> TODO()
231 }
232
addnull233 fun <VM : ViewManager, V : View> VM.add(construct: (Context) -> V, init: V.() -> Unit) {
234 construct(context).apply(init).also {
235 addView(it, ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT))
236 }
237 }
238
buttonnull239 fun ViewManager.button(txt: String, listener: (View) -> Unit) {
240 add(::Button) {
241 text = txt
242 setOnClickListener(listener)
243 }
244 }
245