Android 调用系统应用选文件

我们通常会通过Intent调起系统应用进行选择文件,包括图片、视频、音频等,但是需要考虑不同系统版本的兼容性问题

系统版本 action accept_type(选择文件类型)
<19(4.4) Intent.ACTION_GET_CONTENT 通过intent.setType,设置一个字符串表示MIMEType:“image/*, video/*”
>=19(4.4) Intent.ACTION_OPEN_DOCUMENT
  • intent.setType字符串只接收一个类型,多个无效
  • 通过putExtra的Intent.EXTRA_MIME_TYPES属性,设置string数组指定多种选择类型,此时intent.setType要设置为"*/*"
all Intent.ACTION_PICK 通过setData设置URI,一次只能选择一种类型文件,且类型限于系统API提供的几种,通常选择联系人之类的使用
  1. 指定Intent.CATEGORY_OPENABLE,获取到的都是可以打开stream的URI,不能打开stream的URI不会被选择

  2. 使用ACTION_OPEN_DOCUMENT不可以直接拿到path(除非自己处理),但是可以直接打开stream读取内容(ACTION_GET_CONTENT和ACTION_PICK当然也可以)

  3. H5的input标签会调用WebChromeClient的相应方法(openFileChooser()/onShowFileChooser())(这部分内容可以参考这篇文章),该方法回调会接收URI,并交给前端,前端可以通过URI展示具体文件。

  4. ACTION_GET_CONTENT和ACTION_OPEN_DOCUMENT通过指定boolean类型的Intent.EXTRA_ALLOW_MULTIPLE(API18(4.3)才可以用),使用户可以选择多个文件返回,此时返回的URIs在data.getClipData()中,这里需要注意,在H5的input标签情景下,由于API21开始ValueCallback才接收Uri数组,所以在API18和API19中,不能设置为多选,否则回调只能处理一个Uri。

调用代码

//ACTION_GET_CONTENT ACTION_OPEN_DOCUMENTval intent = Intent()intent.addCategory(Intent.CATEGORY_OPENABLE)if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {  intent.action = Intent.ACTION_OPEN_DOCUMENT  intent.type = "*/*"  val mimeTypes = arrayOf("image/*", "video/*")  intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)  intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)} else {  intent.action = Intent.ACTION_GET_CONTENT  intent.type = "image/*, video/*"}startActivityForResult(Intent.createChooser(intent, "choose file"), 100)//ACTION_PICKval intent = Intent()intent.action = Intent.ACTION_PICKintent.data = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URIstartActivityForResult(Intent.createChooser(intent, "pick file"), 101)

onActivityResult接收代码

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {//4.4之后  //多选从getClipData获取,单选从getData获取  data.clipData?.let {    for (idx in 0 until it.itemCount) {      val item = it.getItemAt(idx)      val uri = item.uri    }  }    //无法直接拿到文件具体path  //1.可直接打开stream读取内容  //                val stream = contentResolver.openInputStream(data.data!!)  //                val bit = BitmapFactory.decodeStream(stream)  //                iv.setImageBitmap(bit)  //2.查到document_id,根据其具体scheme(无法直接拿到path),查到具体path  //参考https://stackoverflow.com/questions/13209494/how-to-get-the-full-file-path-from-uri} else {//4.4之前GET_CONTENT和ACION_PICK都用该方法查询path即可,直接读stream也可以  val projection = arrayOf(MediaStore.Images.Media.DATA)  val cursor = contentResolver.query(data.data!!, projection, null, null, null)  cursor?.let {    val colIdx = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)    if (it.moveToFirst()) {      tv.text = it.getString(colIdx)    }  }  cursor?.close()}

更多相关文章

  1. Eclipse proguard 代码混淆 微信第三方库 Can\'t process class
  2. Android(安卓)安装apk时,报错 Failure [INSTALL_FAILED_TEST_ONLY
  3. android数据库操作之直接读取db文件
  4. Android中JNI调用
  5. pAdTy_-5 保存数据
  6. 设置布局默认为LinearLayout,却成了RelativeLayout
  7. Android(安卓)Studio的下载、安装与配置
  8. RadioGroup和RadioButton单选框
  9. Android(安卓)侧拉选择框

随机推荐

  1. Android Content Framework(1)Concept
  2. android本地定时通知
  3. Android Studio中断开SVN连接
  4. android 网络连接判断
  5. [android]android自动化测试五之Robolect
  6. 引用自定义资源需注意数据类型
  7. Android应用程序键盘(Keyboard)消息处理机
  8. 工作记录[续] android OBB
  9. android系统信息总结
  10. Ubuntu安装Android Studio