分享文件

△概述:如果你要对外提供少量数据,你可以用Intent带着少量数据出去,当你需要对外提供大批量的数据(比如一个图片编辑软件向你请求一个图片资源,一个文档编辑器向你请求一个文档)你将需要分享文件。

△服务器与客户端:我们将请求文件的应用称为客户端,将对外提供数据的应用称为服务器。

△这里所说的文件分享,不是一个应用程序主动分享文件出去(这个功能有其他的实现方式),而是当有应用想要请求文件,你的应用可以将相应的文件提供出去。比如一个社交软件准备发送一张图片,社交软件就相当于是客户端,系统内置那个图库就相当于是服务器,社交软件向图库请求一个图片文件。

服务器的具体步骤如下

配置FileProvider

△想将文件分享出去,首先需要定义一个文件分享者:FileProvider,步骤如下:在配置文件里面增加provider标签:<provider></provider>,这个标签需要指定如下信息:

→指定FileProvider的类。

→指定“authority”属性,通常该属性值一般会是:”包名.fileProvider”。,当FileProvider为你的文件生成URIs时,authorities就是URIs的URI字段内容。

→一个xml文件,你的应用只能将指定的某些路径下的文件分享出去,这些路径由你通过这个XML文件指定。

注:

→xml文件由meta-data子元素来指定。

<providerandroid:name="android.support.v4.content.FileProvider"android.authorities="com.test.fileprovider.fileprovider"android:grantUriPermissions="true"android:exported="false"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:name="@xml/filepaths"/>
</provider>

我当前的包名是:com.test.fileprovider。

△创建上一步所说的XML文件

→在res目录下面新建文件夹,取名xml,在文件夹新建一个文件,取名:filepaths(你可以取你喜欢的名字),

这是按照上图当中resource内容创建。

→xml文件内容:

<?xml version="1.0" encoding="utf-8"?>
<path><!--paths表示你要分享哪个路径下的文件--><files-path path="images/" name="myimages"/>
</path>

解析:

→到此为止,你已经拥有了一个完整的FileProvider。他配置了authority,你想要分享的文件所在路径(或者说是你的应用程序能够分享出去的文件的路径)。

→现在,xml文件指定了如下路径:/data/data/包名/files/images。其实就是你的应用调用方法:getFilesDir()所返回的路径下的images子路径:files/images/。

→name属性内容与文件的路径没有关系,他是你想要在你的URI里面插入的一个字段,如果你在files/images/路径下面有个文件名叫:myImage.jpg。那么fileprovider将会返回:

content://com.test.fileprovider.fileprovider/myimages/myImage.jpg。我们看到,最终的URI里面没有包含images子路径名,而且包含了一个你想插入的name。name属性其实就是为了隐藏真实的路径的。

→所以最终URI是:content://你在清单文件里面所指定的“authority”属性/你的xml文件里指定name属性/你的文件的全名。

→注:在<paths></paths>标签里面你还可以添加多个元素:<cache-path>(对应路径:/data/data/包名/cache)或者<external-path>(对应你的应用程序在SD卡上的默认路径)。

设置一个文件展示以及选择用的窗体

△当你配置了FileProvider,且当有应用向你请求文件时,你需提供一个窗体,该窗体能实现如下功能:(三步)

→可以被请求文件的应用唤起(就是能被隐式Intent唤起)。

→将自己能够分享的文件显示在窗体里(你可以用ListView实现,安卓官方教程也以这个控件作为例子实现)。

→当用户点击了某个文件,该窗体能提供这个文件的URL(就是将URL返回给调用他的窗体)。

△第一步:配置清单文件的过滤器

<activityandroid:name="com.test.fileprovider.ShowFile"><intent-filter><action android:name="android.intent.action.PICK"/><category android:name="android.intent.category.DEFAULT"/><category android:name="android.intent.category.OPENABLE"/><!--设置你想要提供的文件类型--><data android:mimeType="text/plain"/><data android:mimeType="image/*"/></intent-filter>
</activity>

△第二步:通过配置ListView实现(我的代码将分享的路径:手机内存/files/images/,至于如何在内存里创建一个images文件夹,我在这里不再重复)

package com.test.fileprovider;import java.io.File;public class ShowFile extends Activity
{//创建将用到得变量//这些变量主要用于显示一个将分享的文件列表private File filesDir;//他将指向内存路径filesprivate File imageDir;//指向images子路径的:files/imagesprivate File[] imageFiles;//images子路径的所有文件private String[] imageFileNames;//images子路径的所有文件名字private ListView myFileListView = null;private Uri fileUri = null;Intent resultIntent = null;//对变量进行初始化//将文件的名字装填@Overrideprotected void onCreate(bundle savedInstanceState){// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.file_select_activity);//获取ListViewmyFileListView = (ListView)findViewById(R.id.lv_file);//设置IntentresultIntent = new Intent("com.test.fileprovider.ACTION_RETURN_FILE");//获取文件路径以及名字filesDir = getFilesDir();imageDir = new File(filesDir,"images");imageFiles = imageDir.listFiles();//获取images子路径下所有文件//将文件的名字装填imageFileNames = new String[imageFiles.length];for(int i = 0; i<imageFiles.length; i++){imageFileNames[i] = imageFiles[i].getName();}setResult(Activity.RESULT_CANCELED, null);//设置一个默认的返回值/*通过ListView将文件的名字显示出来同时设置ListView响应用户对文件的选择*///将文件名显示出来myFileListView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,imageFileNames));//监听myFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent,View view, int position, long id){// TODO Auto-generated method stub//记录哪个文件被选中了File requestFile = new File(imageDir,imageFileNames[position]);try{//获取文件的URIfileUri = FileProvider.getUriForFile(ShowFile.this,"com.test.fileprovider.fileprovider",requestFile); }catch(Exception e){// TODO: handle exception}/*第三步:当用户选择了某个文件,而且服务器成功地得到文件的URI,将URI返回给客户端。*///如果成功得到了URIif(fileUri!=null){//为RUI添加访问权限resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//设置数据以及数据类型resultIntent.setDataAndType(fileUri, getContentResolver().getType(fileUri));ShowFile.this,setResult(RESULT_OK,resultIntent);}else {resultIntent.setDataAndtype(null, "");ShowFile.this.setResult(RESULT_CANCELED,)}}//OnItemClick方法体  });//setOnItemClickListener}//onCreate方法//这是一个点击事件响应函数//当用户已选择完毕//提供一个按钮按下那时退出窗体public void finished(View view){finish();}
}

现在,服务器的设置已经完成,当有应用需要请求文件,你将可以将你自己的文件给提供出去

△总结:到底服务器都做了什么

→配置FileProvider,指定authorities,指定可分享文件的那个路径(通过配置xml文件)。

→配置<intent-filter>,使他能被客户端的隐式Intent唤起。

→配置ListView,当服务器被唤起时,提供一个可被分享的文件的列表。

→配置点击事件响应,当客户端选择文件,生成文件的URI,同时提供相关权限,并且将该文件的URI给客户端(setResult()方法)。

客户端

△概述:客户端即请求获取某些文件的应用程序。

△客户端要做些什么:

→配置Intent,指定客户端想请求访问什么文件

(1)intent.setAction(Intent.ACTION_PICK);

(2)intent.setType(“image/*”);

→启动访问:当用户想访问某些文件,一般情况下,应当是在某个按钮点击事件响应函数里面执行:执行方法: startActivityForResult(intent, 0);

→当服务器提供了想要的文件,客户端要处理自己所得到的文件。

onActivityResult(int  requestCode, int  resultCode, Intent  returnIntent);

方法里面,returnIntent参数,他带着从服务器里返回来的文件URL,通过他来打开我们想访问的文件

△第一步:配置Intent

//下面哪些TextView用来显示文件信息
//只是方便我调试时使用
import java.io.FileDescriptor;public class MainActivity extends Activity
{private Intent requestIntent = null;private ParcelFileDescriptor mInputPFD = null;//这些TextView都是用来显示文件相关信息private TextView filesUriTextView = null;private TextView fileNameTextView = null;private TextView fileSizeTextView = null;private TextView fileTypeTextView = null;@Overrideprotected void onCreate(Bundle saveInstanceState){super.onCreate(saveInstanceState);setContentView(R.layout.main);requestIntent = new Intent(Intent.ACTION_PICK);requestIntent.setType("image/jpg");//当获取到文件的URI//使用TextView将文件的相关信息显示出来filesUriTextView = (TextView)findViewById(R.id.tv_files_uri);fileNameTextView = (TextView)findViewById(R.id.tv_file_name);fileSizeTextView = (TextView)findViewById(R.id.tv_files_size);fileTypeTextView = (TextView)findViewById(R.id.tv_files_type);}/*第二部:启动访问*///点击事件响应函数public void getsFile(View view){startActivityForResult(requestIntent, 0);}/*第三步:客户端通过RUI处理所得到的文件,以及获取文件相关信息*/@overrideprotected void onActivityResult(int requestCode,int resultCode,Intent returnIntent){// TODO Auto-generated method stubsuper.onActivityResult(requestCode,resultCode,returnIntent);//如果不是正常返回if(resultCode!=RESULT_OK){return;}else{Uri returnUri = returnIntent.getData();//这个方法是自己写来的//用它来获取文件的相关信息getFileInfos(returnUri);try{}catch(FileNotFoundException e){e.printStackTrace();return;}FileDescriptor fd = mInputPFD.getFileDescriptor();}//if}//getFileInfos方法private void getFileInfos(Uri uri){filesUriTextView.setText("uri:"+uri);fileTypeTextView.setText("文件类型:"+getContentResolver.getType(uri));Cursor returnCursor = getContentResolver().query(uri,null,null,null,null);int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);returnCursor.moveToFirst();fileNameTextView.setText("文件名字:"+returnCursor.getString(nameIndex));fileSizeTextView.setText("尺寸:"+returnCursor.getLong(sizeIndex));}}

解析:当服务器窗体退出之后,客户端的onActivityResult()将被调用。returnIntent参数,就是服务器返回的Intent。Intent包含了文件URI,URI里包含文件各种信息。openFileDescriptor()方法返回ParcelFileDesctiptor,通过ParcelFileDescriptor实例,可以得到FileDescriptor对象,客户端可以通过”FileDescriptor”对象读取那个文件。

/*

到此为止你已经得到了一个客户端的程序

*/

△总结:客户端到底做了什么事

→配置一个启动服务器的Intent

→调用方法启动访问

→当得到了服务器的返回信息,处理信息。

安卓下的文件分享——FileProvider相关推荐

  1. 【错误记录】Android 文件分享 FileProvider 设置错误

    文章目录 一.报错信息 二.解决方案 一.报错信息 分享内部存储到文件到其它应用 ; 2021-05-18 16:10:23.480 31881-31881/kim.hsl.file E/DEBUG: ...

  2. 安卓打开rpm文件_微信文件如何分享到QQ?教你一招,不管什么手机都能行

    你是否在工作中遇到这样的难题:工作伙伴在微信给你发了一份重要文件,你想要用手机转发给QQ的好友,但微信和QQ之间又不支持直接分享,这怎么办呢? 是不是有人为了分享文件,特地从手机文件管理器进入到微信. ...

  3. 安卓下快速搜索文件实现历程{NDK}

    我在公司有一个文件浏览器的开发项目,需要很快的去遍历某一路劲下的所有的"图片文件"."视频文件"."音频文件"."文档文件&quo ...

  4. 安卓读取mysql数据库文件路径_Android开发实现读取assets目录下db文件的方法示例...

    本文实例讲述了Android开发实现读取assets目录下db文件的方法.分享给大家供大家参考,具体如下: 最近准备打算写一个关于天气预报的app,偶然的机会在一大神的博客上看到了一个获取天气的api ...

  5. 安卓安装完应用后,如何获取包的meta-inf目录下的文件?

    ============问题描述============ 安卓安装完应用后,可以获取包的meta-inf目录下的文件吗? 在手机上安装完了应用后,然后打开应用,此时,应用里的SDK有没有办法取到应用包 ...

  6. linux共享文件丢失,【干货分享】linux平台下数据文件被误删后,如何及时得知并进行恢复...

    原标题:[干货分享]linux平台下数据文件被误删后,如何及时得知并进行恢复 我们知道在windows平台下,一旦文件在程序中打开,则不能被删除,所以不存在误删数据文件的情况,如下图所示. 但是在LI ...

  7. 安卓上为什么不能用system.io.file读取streammingAssets目录下的文件

    安卓上为什么不能用system.io.file读取streammingAssets目录下的文件 首先,看文档: Streaming Assets Most assets in Unity are co ...

  8. 【安卓开发】调用系统原生的文件分享功能将文件分享给QQ或微信好友

    调用系统原生的文件分享功能将文件分享给QQ或微信好友 核心代码: //传入的fileName是文件名的全路径@SuppressLint("QueryPermissionsNeeded&quo ...

  9. 安卓手机Android文件夹下obb文件是什么,obb是什么文件?怎么使用obb文件夹

    类型:休闲益智大小:46.4M语言:英文 评分:5.0 标签: 立即下载 obb文件就是所谓的游戏数据包,只不过有的obb文件被压缩成了压缩文件.数据包的使用直接影响游戏的进程.下载数据包之后,可能还 ...

最新文章

  1. 计算机表格大小怎么调整,excel表格如何调整表格大小
  2. 霸榜COCO和Cityscapes!南理工CMU提出极化自注意力,更精细的双重注意力建模结构
  3. JAVA常用框架和插件
  4. 成为“能打”的二次元游戏《明日方舟》做对了什么?
  5. 进度条的另外一种用法
  6. iOS中几种定时器 - 控制了时间,就控制了一切
  7. cypress测试框架与selenium_selenium自动化测试框架之PO设计模式
  8. 完全硬件实现的忆阻器卷积神经网络
  9. linux 挂载san存储,新手看招:Linux操作系统下挂载SAN资源
  10. MySQL--自增列学习
  11. implay matlab,matlab free download - SourceForge
  12. 记录——《C Primer Plus (第五版)》第九章编程练习第六题
  13. LINUX 中htop的安装
  14. jsp 判断时间大小
  15. 基于Java的体育场地预约系统
  16. 健康医药企业营销数字化心法100条
  17. java 密码生成器_[Java小白]WIFI纯数字密码字典生成器
  18. Android 权限汇总大全
  19. 【PPT】学术答辩163套模板
  20. 如何卸载AutoCAD 2019,彻底卸载MAC版CAD教程

热门文章

  1. php 数组去重函数,【译】更快的方式实现PHP数组去重
  2. 【冰糖Python】Scipy:非参数检验 Mann-Whitney rank test、Wilcoxon signed rank test、Chi-square test
  3. FPGA入门学习笔记(十四)Vivado实现数码管段码显示以及动态扫描
  4. 如何无损压缩证件照?有没有免费的方法
  5. 腾讯云轻量8核16G18M服务器带宽CPU系统盘性能测评
  6. 莫比乌斯反演新手入门及练习题
  7. Grounding DINO-开集目标检测论文解读
  8. 前端进阶(十八)js多线程
  9. 第八章数组和矩阵问题(一)
  10. 我花了10天学习全自动软件开发,结果居然.....