前一天讲到合约(Contracts)和启动器(Launcher)取代StartActivityForResult,官方也帮我们建立了14种常见的合约模板,以下是官方的14种合约
ActivityResultContracts.CreateDocument()
ActivityResultContracts.GetContent()
ActivityResultContracts.GetMultipleContents()
ActivityResultContracts.OpenDocument()
ActivityResultContracts.OpenDocumentTree()
ActivityResultContracts.OpenMultipleDocuments()
ActivityResultContracts.PickContact()
ActivityResultContracts.RequestMultiplePermissions()
ActivityResultContracts.RequestPermission()
ActivityResultContracts.StartActivityForResult()
ActivityResultContracts.StartIntentSenderForResult()
ActivityResultContracts.TakePicture()
ActivityResultContracts.TakePicturePreview()
ActivityResultContracts.TakeVideo()
这篇先介绍
An ActivityResultContract to prompt the user to select a path for creating a new document, returning the content: Uri of the item that was created.
The input is the suggested name for the new file.This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
CreateDocument()
可以用在拍照前的建立空白档案。
以下范例是建立空白的saberEat.jpg
档案,然後回传档案的content://uri
,需要注意使用者可以更改档案名称。
createDocumentResultLauncher.launch("saberEat.jpg")
private val createDocumentResultLauncher =
registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
Log.d("maho", "回传: $uri")
}
实际执行程序後的Log
D/maho: 回传: content://com.android.providers.downloads.documents/document/1692
An ActivityResultContract to prompt the user to pick a piece of content, receiving a content:// Uri for that content that allows you to use android.content.ContentResolver.openInputStream(Uri) to access the raw data. By default, this adds Intent.CATEGORY_OPENABLE to only return content that can be represented as a stream.
The input is the mime type to filter by, e.g. image/*.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
以下范例是输入一个MIME type
指定类型,然後选择一个档案,回传档案的content://uri
,不可以输入null
。
getContentResultLauncher.launch("image/*")
private val getContentResultLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
Log.d("maho", "回传: $uri")
}
实际执行程序後的Log
D/maho: 回传: content://com.android.providers.downloads.documents/document/1688
An ActivityResultContract to prompt the user to pick one or more a pieces of content, receiving a content:// Uri for each piece of content that allows you to use android.content.ContentResolver.openInputStream(Uri) to access the raw data. By default, this adds Intent.CATEGORY_OPENABLE to only return content that can be represented as a stream.
The input is the mime type to filter by, e.g. image/*.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
以下范例是输入一个MIME type
指定类型,然後长按选择多个档案,用阵列的形式回传档案的content://uri
,不可以输入null
。
getMultipleContentsResultLauncher.launch("image/*")
private val getMultipleContentsResultLauncher =
registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { uri ->
Log.d("maho", "回传: $uri")
}
实际执行程序後的Log
D/maho: 回传: [
content://com.android.providers.downloads.documents/document/1688,
content://com.android.providers.downloads.documents/document/1677
]
An ActivityResultContract to prompt the user to open a document, receiving its contents as a file:/http:/content: Uri.
The input is the mime types to filter by, e.g. image/*.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
See Also: DocumentsContract
以下范例是输入多个MIME type
指定类型,然後选择一个档案,回传档案的content://uri
,可以输入null
表示不指定类型。
openDocumentResultLauncher.launch(arrayOf("image/jpeg", "video/mp4"))
private val openDocumentResultLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
Log.d("maho", "回传: $uri")
}
实际执行程序後的Log
D/maho: 回传: content://com.android.providers.downloads.documents/document/1677
An ActivityResultContract to prompt the user to select a directory, returning the user selection as a Uri. Apps can fully manage documents within the returned directory.
The input is an optional Uri of the initial starting location.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
See Also:
Intent.ACTION_OPEN_DOCUMENT_TREE, DocumentsContract.buildDocumentUriUsingTree, DocumentsContract.buildChildDocumentsUriUsingTree
以下范例是选择资料夹,然後回传资料夹的content://uri
,可以输入null
表示不指定路径。
openDocumentTreeResultLauncher.launch(null)
private val openDocumentTreeResultLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
Log.d("maho", "回传: $uri")
}
选择Download/Duo
资料夹,实际执行程序後的Log
D/maho: 回传: content://com.android.externalstorage.documents/tree/primary%3ADownload%2FDuo
An ActivityResultContract to prompt the user to open (possibly multiple) documents, receiving their contents as file:/http:/content: Uris.
The input is the mime types to filter by, e.g. image/*.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
See Also:
DocumentsContract
以下范例是输入多个MIME type
指定类型,然後选择多个档案,用阵列的形式回传档案的content://uri
,不可以输入null
。
openMultipleDocumentsResultLauncher.launch(arrayOf("image/jpeg", "video/mp4"))
private val openMultipleDocumentsResultLauncher =
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { list ->
Log.d("maho", "回传: $list")
}
实际执行程序後的Log
D/maho: 回传: [
content://com.android.providers.media.documents/document/image%3A5789,
content://com.android.providers.media.documents/document/image%3A5791
]
An ActivityResultContract to request the user to pick a contact from the contacts app.
The result is a content: Uri.
See Also:
ContactsContract
选择单个连络人,回传content://uri
pickContactResultLauncher.launch(null)
private val pickContactResultLauncher =
registerForActivityResult(ActivityResultContracts.PickContact()) { uri ->
Log.d("maho", "回传: $uri")
}
实际执行程序後的Log
D/maho: 回传: content://com.android.contacts/contacts/lookup/1519iaad44c18aa14d9a/10
An Intent action for making a permission request via a regular Activity.startActivityForResult API. Caller must provide a String[] extra EXTRA_PERMISSIONS Result will be delivered via Activity.onActivityResult(int, int, Intent) with String[] EXTRA_PERMISSIONS and int[] EXTRA_PERMISSION_GRANT_RESULTS, similar to Activity.onRequestPermissionsResult(int, String[], int[])
See Also:
Activity.requestPermissions(String[], int), Activity.onRequestPermissionsResult(int, String[], int[])
Key for the extra containing all the requested permissions.
See Also:
ACTION_REQUEST_PERMISSIONS
Key for the extra containing whether permissions were granted.
See Also:
ACTION_REQUEST_PERMISSIONS
以下范例是输入多个系统权限,用map的形式回传每个权限的true
和false
,可以输入null
,不过没意义。
requestMultiplePermissionsResultLauncher.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
)
private val requestMultiplePermissionsResultLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { map ->
Log.d("maho", "回传: $map")
}
实际执行程序後的Log
D/maho: 回传: {
android.permission.CAMERA=false,
android.permission.WRITE_EXTERNAL_STORAGE=false
}
An ActivityResultContract to request a permission
以下范例是输入一个系统权限,回传权限的true
和false
,可以输入null
,不过没意义。
requestPermissionResultLauncher.launch(Manifest.permission.CAMERA)
private val requestPermissionResultLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { boolean ->
Log.d("maho", "回传: $boolean")
}
实际执行程序後的Log
D/maho: 回传: false
An ActivityResultContract that calls Activity.startIntentSender(IntentSender, Intent, int, int, int). This ActivityResultContract takes an IntentSenderRequest, which must be constructed using an IntentSenderRequest.Builder. If the call to Activity.startIntentSenderForResult(IntentSender, int, Intent, int, int, int) throws an IntentSender.SendIntentException the androidx.activity.result.ActivityResultCallback will receive an ActivityResult with an Activity.RESULT_CANCELED resultCode and whose intent has the action of ACTION_INTENT_SENDER_REQUEST and an extra EXTRA_SEND_INTENT_EXCEPTION that contains the thrown exception.
我不知道这个是做什麽用的,Google後才知道是Phone Selector Api,可以用来做简讯验证之类的功能。
//implementation 'com.google.android.gms:play-services-auth:19.2.0'
val hintRequest = HintRequest
.Builder()
.setPhoneNumberIdentifierSupported(true)
.build()
val credentialsOptions = CredentialsOptions
.Builder()
.forceEnableSaveDialog()
.build()
val credentials = Credentials
.getClient(this, credentialsOptions)
.getHintPickerIntent(hintRequest)
startIntentSenderForResultResultLauncher.launch(
IntentSenderRequest
.Builder(credentials)
.build()
)
private val startIntentSenderForResultResultLauncher =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
if (RESULT_OK == result.resultCode) {
val credential: Credential? = result
.data
?.getParcelableExtra(Credential.EXTRA_KEY)
Log.d(
"maho",
"id: ${credential?.id} " +
"\naccountType: ${credential?.accountType} " +
"\nfamilyName: ${credential?.familyName} " +
"ngivenName: ${credential?.givenName} " +
"\nidTokens: ${credential?.idTokens} " +
"\nname: ${credential?.name} " +
"\npassword: ${credential?.password} " +
"\nprofilePictureUri: ${credential?.profilePictureUri}"
)
}
}
实际执行程序後的Log
D/maho: id: +886910123456
accountType: null
familyName: null
givenName: null
idTokens: []
name: null
password: null
profilePictureUri: null
An ActivityResultContract to take a picture saving it into the provided content-Uri.
Returns true if the image was saved into the given Uri.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
以下范例是建立空白档案後再开启相机拍摄照片,回传true
表示储存成功,false
表示储存失败。
第一种写法:用ActivityResultContracts.CreateDocument()
建立档案,取得档案的uri
後再使用TakePicture()
拍照
takePictureCreateDocumentResultLauncher.launch("002.jpg")
private val takePictureCreateDocumentResultLauncher =
registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
takePictureResultLauncher.launch(uri)
}
private val takePictureResultLauncher =
registerForActivityResult(ActivityResultContracts.TakePicture()) { boolean ->
Log.d("maho", "回传: $boolean")
}
实际执行程序後的Log
//ActivityResultContracts.CreateDocument()的Log
D/maho: 回传: content://com.android.providers.downloads.documents/document/1701
//ActivityResultContracts.TakePicture()的Log
D/maho: 回传: true
第二种写法:使用File()
建立档案,再使用getUriForFile()
取得档案的uri
後再使用TakePicture()
拍照
val picturePath = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "003.jpg")
val uri = getUriForFile(this, "$packageName.fileprovider", picturePath)
takePictureResultLauncher.launch(uri)
private val takePictureResultLauncher =
registerForActivityResult(ActivityResultContracts.TakePicture()) { boolean ->
Log.d("maho", "回传: $boolean")
}
如果要用第二种写法还要前置作业
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="lens_picture"
path="." />
</paths>
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/tool_provider_paths" />
</provider>
</application>
</manifest>
实际执行程序後的Log
D/maho: 回传: true
An ActivityResultContract to take small a picture preview, returning it as a Bitmap.
This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
以下范例是开启相机,拍摄照片後回传相片缩图的bitmap
,因为是缩图,所以图片会非常小,官方文件表示 take small a picture preview,所以我也不太懂这个可以用来做什麽功能。
takePicturePreviewResultLauncher.launch(null)
private val takePicturePreviewResultLauncher =
registerForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap ->
amIvTakePicturePreview.setImageBitmap(bitmap)
//把缩图存起来的程序码
val picturePath = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "004.jpg")
val fileOutputStream = FileOutputStream(picturePath)
val bufferedOutputStream = BufferedOutputStream(fileOutputStream)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bufferedOutputStream)
bufferedOutputStream.flush()
bufferedOutputStream.close()
}
实际执行程序後的Log
D/maho: 回传: android.graphics.Bitmap@93f6ede
An ActivityResultContract to take a video saving it into the provided content-Uri.
Returns a thumbnail.This can be extended to override createIntent if you wish to pass additional extras to the Intent created by super.createIntent().
以下范例是建立空白档案後再开启相机录制影片,录制完後回传影片缩图的bitmap
。
//路径为空,会储存到 DCIM 资料夹
takeVideoResultLauncher.launch(null)
//指定储存路径
val picturePath = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "005.mp4")
val uri = getUriForFile(this, "$packageName.fileprovider", picturePath)
takeVideoResultLauncher.launch(uri)
private val takeVideoResultLauncher =
registerForActivityResult(ActivityResultContracts.TakeVideo()) { bitmap ->
amIvTakeVideo.setImageBitmap(bitmap)
}
实际执行程序後的Log,影片有储存成功,理论上要回传影片缩图的bitmap
,但我在Android 11
一直试不出来,StackOverflow也有一样的问题,也还没解决,只能说是官方的坑
D/maho: 回传: null
我自己觉得官方合约的命名方式满混乱的,开启档案就有Get
和Open
,然後档案本身也有Document
和Content
,所以来分类一下
输入单个档案类型 | 输入多个档案类型 | |
---|---|---|
回传单个档案uri | GetContent() | OpenDocument() |
回传阵列档案uri | GetMultipleContents() | OpenMultipleDocuments() |
输入单个权限 | 输入多个权限 | |
---|---|---|
回传单个权限验证结果 | RequestPermission() | X |
回传阵列权限验证结果 | X | RequestMultiplePermissions() |
相片 | 相片缩图 | 影片 | |
---|---|---|---|
回传布林值 | TakePicture() | X | X |
回传相片缩图bitmap | X | TakePicturePreview() | X |
回传影片缩图bitmap | X | X | TakeVideo() |
程序码放在feature/resultTemplate
分支
https://github.com/AndyAWD/AndroidSystem/tree/feature/resultTemplate
资料型别 JavaScript 的型别主要可以分成基本型别 (Primitives)与物件型别 ...
之前上课时jQuery讲师说到: :nth-child(b) b要从1开始,不知道为什麽 比如$('...
鬼故事 - 我不晓得这东西为甚麽会动 source: starecat.com 故事开始 故事主角:...
前言 在 上一篇文章 中讲完了 Zettelkasten 笔记法,这篇文章来讲它的优化版本 - An...
Day 22 - 谈谈我对Android的兴趣 认识Android 小时候我拿到我第一台手机,那时我...