网站推广究竟应该怎么做,表情包制作赚钱软件app哪个好用,企业形象设计课程标准,举报网站建设超级轻量级FilePicker测试没有问题
本文摘录于#xff1a;https://blog.csdn.net/gitblog_00365/article/details/141449437只是做学习备份之用#xff0c;绝无抄袭之意#xff0c;有疑惑请联系本人#xff01; 今天真的是发了疯的找文件管理器,因为调用系统自带的文件管理…超级轻量级FilePicker测试没有问题
本文摘录于https://blog.csdn.net/gitblog_00365/article/details/141449437只是做学习备份之用绝无抄袭之意有疑惑请联系本人 今天真的是发了疯的找文件管理器,因为调用系统自带的文件管理器老是有问题,所以越调越着急,最后发现还是FilePicker简单好用,代码仓库地址:https://gitcode.com/gh_mirrors/andr/android-filepicker/overview?utm_sourceartical_gitcodeindextoptypecardwebUrl 步骤很简单,第一步添加依赖 首先在你的项目的 build.gradle (Module) 文件中的 dependencies 块添加如下依赖
implementation com.github.angads25:filepicker:1.1.0然后在代码黄总增加如下内容(原文内容):
import com.angads25.filepicker.model.FilePath;
import com.angads25.filepicker.view.FilePickerFragment;...// 在某个方法内启动FilePicker
private void chooseFile() {FilePickerFragment filePickerFragment FilePickerFragment.newInstance();filePickerFragment.setFileType(FilePickerFragment.FILE_TYPE_ALL);filePickerFragment.setOnFilePathSelectedListener(new FilePickerFragment.OnFilePathSelectedListener() {Overridepublic void onFilePathSelected(ListFilePath filePaths) {// 处理选择的文件路径for (FilePath fp : filePaths) {Log.d(MyApp, Selected Path: fp.getPath());}}});filePickerFragment.show(getSupportFragmentManager(), FILE_PICKER);
}我自己的代码如下:
public void onClickSelectFile(View view) {Toast.makeText(getApplicationContext(), 请选择bin格式文件, Toast.LENGTH_SHORT).show();DialogProperties properties new DialogProperties();properties.selection_mode DialogConfigs.SINGLE_MODE;properties.selection_type DialogConfigs.FILE_SELECT;properties.root new File(/sdcard);properties.error_dir new File(DialogConfigs.DEFAULT_DIR);properties.offset new File(DialogConfigs.DEFAULT_DIR);String[] extensions {bin,};properties.extensions extensions;FilePickerDialog dialog new FilePickerDialog(OTA_Active.this, properties);dialog.setTitle(请选择bin格式文件);dialog.setDialogSelectionListener(new DialogSelectionListener() {Overridepublic void onSelectedFilePaths(String[] files) {// files数组包含了用户由应用程序选择的文件路径。String pathfiles[0];if(path!) {int start path.lastIndexOf(/);if (start ! -1 ) {FileNameList.add(path.substring(start 1));FilePathList.add(path);ArrayAdapterString array new ArrayAdapter(OTA_Active.this, android.R.layout.simple_list_item_1, FileNameList);listview.setAdapter(array);OTA_Active.this.runOnUiThread(new Runnable() {Overridepublic void run() {//此时已在主线程中可以更新UI了AdapterView.OnItemClickListener onItemClickListener listview.getOnItemClickListener();if(onItemClickListener!null){onItemClickListener.onItemClick(listview,null,listview.getCount()-1,0);}}});}}}});dialog.show();}本章节的源码可以从如下地址下载:https://download.csdn.net/download/chengdong1314/89943454 测试确实可行,使用起来完全没问题,视频操作演示如下: 选择文件操作 挣扎解决自带文件管理器获取不到绝对地址问题
非常无奈按照网上的方法调用系统自带的文件管理器选择文件的时候总会这样返回msf%3A1000038197之类的数据,比如如下:
content://com.android.providers.downloads.documents/document/msf%3A1000038197本文摘录于https://cloud.tencent.com/developer/article/2003648只是做学习备份之用绝无抄袭之意有疑惑请联系本人 这里根据上面的文章调用如下函数: public static File uriToFileApiQ(Uri uri, Context context) {File file null;if (uri null) return file;//android10以上转换if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {file new File(uri.getPath());} else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {//把文件复制到沙盒目录ContentResolver contentResolver context.getContentResolver();String displayName System.currentTimeMillis() Math.round((Math.random() 1) * 1000) . MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));try {InputStream is contentResolver.openInputStream(uri);File cache new File(context.getCacheDir().getAbsolutePath(), displayName);FileOutputStream fos new FileOutputStream(cache);FileUtils.copy(is, fos);file cache;fos.close();is.close();} catch (IOException e) {e.printStackTrace();}}return file;}这样调用uriToFileApiQ函数:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode Activity.RESULT_OK) {Uri uri data.getData();if (Build.VERSION.SDK_INT Build.VERSION_CODES.KITKAT) {//4.4以后File fi uriToFileApiQ(this, uri);pathfi.getPath();} else {//4.4以下下系统调用方法path getRealPathFromURI(uri);}int index path.lastIndexOf(.);if (index 0) {if(!(bin.equals(path.substring(index 1))))return;}else return;if(path!) {int start path.lastIndexOf(/);if (start ! -1 ) {FileNameList.add(path.substring(start 1));FilePathList.add(path);ArrayAdapterString array new ArrayAdapter(OTA_Active.this, android.R.layout.simple_list_item_1, FileNameList);listview.setAdapter(array);AdapterView.OnItemClickListener onItemClickListener listview.getOnItemClickListener();if(onItemClickListener!null){onItemClickListener.onItemClick(listview,null,listview.getCount()-1,0);}}}}}onActivityResult是这样引起的: public void onClickSelectFile(View view) {Toast.makeText(getApplicationContext(), 请选择bin格式文件, Toast.LENGTH_SHORT).show();Intent intent new Intent(Intent.ACTION_GET_CONTENT);intent.setType(*/*);//无类型限制intent.addCategory(Intent.CATEGORY_OPENABLE);startActivityForResult(intent, 1);}上面的uriToFileApiQ函数是有缺陷的,FileUtils.copy(is, fos);函数报错了,如果改成FileUtils.copy(is.tostring(), fos.tostring());确实编译没错了,但是拷贝到沙盒里面的文件大小是0,拷贝出错! 无奈啊,我这时候都放弃了,又去本文第一节去尝试了一圈,搞定了自定义文件管理器的问题,但是客户又说一定要自带的资源管理器,可以打开最近的文件,无奈只能够死磕这个问题!!! 最后找呀找,找到这篇文章:https://www.bytezonex.com/archives/b8w3-cvz.html 这里说明了原来的拷贝错误的原因: Android 10 获取文件路径难题/document/msf: 解决方案
许多开发者在 Android 10 设备上使用 Intent.ACTION_GET_CONTENT 获取文件路径时都会遇到返回路径形如 /document/msf: 的情况令人困惑不已。这并非应用本身的错误而是 Android 10 为了加强隐私保护而采取的新策略。本文将深入剖析这一变化背后的原因并提供一套完整的解决方案帮助你绕过障碍顺利获取目标文件。
从文件路径到 URIAndroid 10 文件访问机制的转变 在 Android 10 之前应用能够通过文件路径直接访问设备上的绝大多数文件这种方式虽然便捷但也存在着巨大的安全隐患容易造成用户隐私泄露。为了提升系统安全性Android 10 引入了分区存储机制限制应用直接访问外部存储空间。
新的机制下当应用使用 Intent.ACTION_GET_CONTENT 选择文件时系统不再返回直接的文件路径而是返回一个 content:// 格式的 URI。这个 URI 指向一个由 MediaStore 管理的中间层应用无法直接从中获取文件路径相当于在应用和真实文件之间建立了一道安全屏障。
神秘的 /document/msf: 特殊文件的安全处理 /document/msf: 正是 Android 10 返回的一种特殊 URI它通常代表着应用选择的并非媒体文件例如图片、视频而是其他类型的文件。由于系统无法确定应用如何使用这些文件为了最大程度地保护用户隐私系统选择不直接提供文件路径而是返回这个特殊的 URI将文件访问权限牢牢掌握在自己手中。
ContentResolver 和 InputStream突破封锁的利器 想要在 Android 10 上顺利获取文件内容我们需要借助 Android 系统提供的 ContentResolver 和 InputStream 这两大利器。
操作步骤
获取 ContentResolver 通过 context.contentResolver 获取 ContentResolver 实例相当于获取了与 MediaStore 通信的桥梁。 打开 InputStream 使用 ContentResolver.openInputStream(uri) 方法将获取的 content:// URI 传递进去打开一个指向目标文件的 InputStream相当于在安全屏障上打开了一条通道文件内容将通过这条通道流向应用。 读取文件内容 使用 InputStream 的 read() 方法如同读取水流一般将文件内容源源不断地读取出来供应用使用。 整体思路就是通过InputStream 把数据从外部储存转写到沙盒来,最后修改uriToFileApiQ函数如下: public static File uriToFileApiQ(Context context,Uri uri) {File file null;if(uri null) return file;//android10以上转换if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {file new File(uri.getPath());} else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {//把文件复制到沙盒目录ContentResolver contentResolver context.getContentResolver();
// String displayName System.currentTimeMillis() Math.round((Math.random() 1) * 1000)
// . MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));// 注释掉的方法可以获取到原文件的文件名但是比较耗时Cursor cursor contentResolver.query(uri, null, null, null, null);String displayName;if (cursor.moveToFirst()) {displayName cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));}try {InputStream in contentResolver.openInputStream(uri);File cache new File(context.getCacheDir().getAbsolutePath(), displayName);FileOutputStream out new FileOutputStream(cache);//FileUtils.copy(in.toString(), out.toString());int len-1;byte[] bnew byte[512*1024];while((lenin.read(b))!-1){out.write(b,0,len);}file cache;in.close();out.close();} catch (IOException e) {e.printStackTrace();}}return file;}这里测试到拷贝过来的文件大小就对了,到此问题成功解决! 本章节的安卓源码从如下地址下载:https://download.csdn.net/download/chengdong1314/89943485 视频操作如下: