Android(安卓)调用系统应用选文件
16lz
2021-01-26
Android 调用系统应用选文件
我们通常会通过Intent调起系统应用进行选择文件,包括图片、视频、音频等,但是需要考虑不同系统版本的兼容性问题
系统版本 | action | accept_type(选择文件类型) |
---|---|---|
<19(4.4) | Intent.ACTION_GET_CONTENT | 通过intent.setType,设置一个字符串表示MIMEType:“image/*, video/*” |
>=19(4.4) | Intent.ACTION_OPEN_DOCUMENT |
|
all | Intent.ACTION_PICK | 通过setData设置URI,一次只能选择一种类型文件,且类型限于系统API提供的几种,通常选择联系人之类的使用 |
-
指定Intent.CATEGORY_OPENABLE,获取到的都是可以打开stream的URI,不能打开stream的URI不会被选择
-
使用ACTION_OPEN_DOCUMENT不可以直接拿到path(除非自己处理),但是可以直接打开stream读取内容(ACTION_GET_CONTENT和ACTION_PICK当然也可以)
-
H5的input标签会调用WebChromeClient的相应方法(openFileChooser()/onShowFileChooser())(这部分内容可以参考这篇文章),该方法回调会接收URI,并交给前端,前端可以通过URI展示具体文件。
-
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()}
更多相关文章
- Eclipse proguard 代码混淆 微信第三方库 Can\'t process class
- Android(安卓)安装apk时,报错 Failure [INSTALL_FAILED_TEST_ONLY
- android数据库操作之直接读取db文件
- Android中JNI调用
- pAdTy_-5 保存数据
- 设置布局默认为LinearLayout,却成了RelativeLayout
- Android(安卓)Studio的下载、安装与配置
- RadioGroup和RadioButton单选框
- Android(安卓)侧拉选择框