Skip to content

基础用法 (Kotlin)

DylanCai edited this page Jul 24, 2021 · 12 revisions

Kotlin | Java

开始使用

用法只有简单的两步:

第一步,创建对应功能的启动器对象

ComponentActivityFragment 创建对应的对象,需要注意创建对象的时机要在 onStart() 之前。

例如创建通用的启动器:

private val startActivityLauncher = StartActivityLauncher(this)

提供以下默认的启动器类:

启动器 作用
StartActivityLauncher 完美替代 startActivityForResult()
TakePicturePreviewLauncher 调用系统相机拍照预览,返回 Bitmap
TakePictureLauncher 调用系统相机拍照,返回 Uri
TakeVideoLauncher 调用系统相机录像,返回 Uri
PickContentLauncher, GetContentLauncher 选择单个图片或视频,已适配 Android 10
GetMultipleContentsLauncher 选择多个图片或视频,已适配 Android 10
CropPictureLauncher 裁剪图片,已适配 Android 11
RequestPermissionLauncher 请求单个权限
RequestMultiplePermissionsLauncher 请求多个权限
AppDetailsSettingsLauncher 打开系统设置的 App 详情页
EnableBluetoothLauncher 打开蓝牙
EnableLocationLauncher 打开定位
CreateDocumentLauncher 创建文档
OpenDocumentLauncher 打开单个文档
OpenMultipleDocumentsLauncher 打开多个文档
OpenDocumentTreeLauncher 访问目录内容
PickContactLauncher 选择联系人
StartIntentSenderLauncher 替代 startIntentSender()

第二步,调用对应的 launch 方法

完美替代 startActivityForResult()

跳转 activity 得到回调结果:

startActivityLauncher.launch<InputTextActivity>(KEY_NAME to "nickname") { resultCode, data ->
  if (resultCode == RESULT_OK) {
    val value = data?.getStringExtra(KEY_VALUE)
    // 处理回调结果
  }
}

也可以通过 intent 进行跳转:

startActivityLauncher.launch(intent) { resultCode, data ->
  if (resultCode == RESULT_OK) {
    // 处理回调结果
  }
}

拍照预览

调用系统相册拍照后返回 Bitmap,仅仅用作展示。

takePicturePreviewLauncher.launch { bitmap ->
  if (bitmap != null) {
    imageView.setImageBitmap(bitmap)
  }
}

拍照

调用系统相机拍照,保存到应用缓存目录:

takePictureLauncher.launch { uri ->
  if (uri != null) {
    // 拍照成功,上传或取消等操作后建议把缓存文件删除
  }
}

保存到系统相册:

takePictureLauncher.launchForMediaImage { uri ->
  if (uri != null) {
    // 拍照成功
  }
}

录像

调用系统相机录像,保存到应用缓存目录:

takeVideoLauncher.launch { uri ->
  if (uri != null) {
    // 录像成功,上传或取消等操作后建议把缓存文件删除
  }
}

保存到系统相册:

takeVideoLauncher.launchForMediaVideo { uri ->
  if (uri != null) {
    // 录像成功
  }
}

选择单个图片或视频

PickContentLauncherGetContentLauncher 可供选择,对应 Intent 的 action 分别是 Intent.ACTION_PICKIntent.ACTION_GET_CONTENT。官方建议用 Intent.ACTION_GET_CONTENT,但是会跳转一个 Material Design 的选择文件页面,比较有割裂感通常不符合需求,而 Intent.ACTION_PICK 才会跳转相册页面。可以两个都试一下再做选择。

选择图片调用 launchForImage(),选择视频调用 launchForVideo()

pickContentLauncher.launchForImage(
  onActivityResult = { uri ->
    if (uri != null) {
      // 处理 uri
    }
  },
  onPermissionDenied = { settingsLauncher ->
    // 拒绝了读取权限且不再询问,可引导用户到设置里授权该权限
  },
  onExplainRequestPermission = {
    // (可选)拒绝了一次读取权限,可弹框解释为什么要获取该权限
  }
)

选择多个图片或视频

只有 GetMultipleContentsLauncher 可以选择,对应 Intent 的 action 是 Intent.ACTION_GET_CONTENTIntent.ACTION_PICK 不支持多选。

选择图片调用 launchForImage(),选择视频调用 launchForVideo()

getMultipleContentsLauncher.launchForImage(
  onActivityResult = { uris ->
    if (uris.isNotEmpty()) {
      // 处理 uri 列表
    }
  },
  onPermissionDenied = { settingsLauncher ->
    // 拒绝了读取权限且不再询问,可引导用户到设置里授权该权限
  },
  onExplainRequestPermission = {
    // (可选)拒绝了一次读取权限,可弹框解释为什么要获取该权限
  }
)

裁剪图片

cropPictureLauncher.launch(inputUri) { uri ->
  if (uri != null) {
    // 处理 uri
  }
}

请求单个权限

requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION,
  onGranted = {
    // 已同意
  },
  onDenied = { settingsLauncher ->
    // 拒绝且不再询问,可引导用户到设置里授权该权限
  },
  onExplainRequest = {
    // (可选)拒绝了一次,可弹框解释为什么要获取该权限
  }
)

请求多个权限

requestMultiplePermissionsLauncher.launch(
  Manifest.permission.ACCESS_FINE_LOCATION,
  Manifest.permission.READ_EXTERNAL_STORAGE,
  onAllGranted = {
    // 已全部同意
  },
  onDenied = { deniedList, settingsLauncher ->
    // 拒绝且不再询问,可引导用户到设置里授权该权限
  },
  onExplainRequest = { deniedList ->
    // (可选)拒绝了一次,可弹框解释为什么要获取该权限
  }
)

打开系统设置的 App 详情页

// appDetailsSettingsLauncher.launch()
appDetailsSettingsLauncher.launch {
  // 回调逻辑
}

打开蓝牙

由于蓝牙功能需要 GPS 定位,除了打开蓝牙,还会需要授权定位权限和确保定位已打开才能正常使用,所以增加以下用法。

enableBluetoothLauncher.launchAndEnableLocation(
  "为保证蓝牙正常使用,请开启定位",  // 已授权权限但未开启定位,会跳转对应设置页面,并吐司该字符串
  onLocationEnabled= { enabled ->
    if (enabled) {
      // 已开启了蓝牙,并且授权了位置权限和打开了定位
    }
  },
  onPermissionDenied = { settingsLauncher ->
    // 拒绝了位置权限且不再询问,可引导用户到设置里授权该权限
  },
  onExplainRequestPermission = {
    // (可选)拒绝了一次位置权限,可弹框解释为什么要获取该权限
  }
)

打开定位

enableLocationLauncher.launch { enabled ->
  if (enabled) {
    // 已开启定位
  }
}

创建文档

createDocumentLauncher.launch(filename) { uri ->
  if (uri != null) {
    // 处理 uri
  }
}

打开单个文档

openDocumentLauncher.launch("application/*") { uri ->
  if (uri != null) {
    // 处理 uri
  }
}

打开多个文档

openMultipleDocumentsLauncher.launch("application/*") { uris ->
  if (uris.isNotEmpty()) {
    // 处理 uri 列表
  }
}

访问目录内容

openDocumentTreeLauncher.launch { uri ->
  if (uri != null) {
    val documentFile = DocumentFile.fromTreeUri(context, uri)
    // 处理文档文件
  }
}

选择联系人

pickContactLauncher.launch { uri ->
  if (uri != null) {
    // 处理 uri
  }
}

替代 startIntentSender()

startIntentSenderLauncher.launch(intentSender, fillInIntent, flagsValues, flagsMask) { resultCode, data ->
  if (resultCode == RESULT_OK) {
    // 处理回调结果
  }
}