原文地址:http://android.xsoftlab.net/training/secure-file-sharing/share-file.html

一旦APP设置通过URI的方式共享文件,你需要响应其它APP请求这些文件的请求。响应这些请求的一种方式是,在服务端APP上提供一个文件选择接口,以便其它的程序可以调用。这种方法允许客户端程序的用户从服务端选择一个文件,然后接收被选择文件的URI地址。

这节课展示了如何在Activity中创建文件选择功能,以便响应文件请求。

接收文件请求

为了接收客户端APP的文件请求,以及以URI的方式作出响应,APP应该在Activity中提供文件选择器。这样的话,客户端APP可以通过调用startActivityForResult()方法启动这个Activity。当客户端调用了startActivityForResult()方法,你的APP可以返回一个结果给客户端APP,这个结果以URI的形式将用户选择的文件返回。

有关学习如何在客户端APP中实现文件的请求,请参见课程: Requesting a Shared File。

创建一个文件选择器Activity

为了设置文件选择器Activity,首选需要在清单文件中指定activity,并在其中附加意图过滤器,这个意图过滤器用来匹配行为ACTION_PICK以及类别CATEGORY_DEFAULT和CATEGORY_OPENABLE。还要给服务端给客户端提供的文件添加MIME类型过滤器。下面的代码片段展示了如何指定一个新Activity以及过滤器:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">...<application>...<activity
                android:name=".FileSelectActivity"android:label="@"File Selector" ><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>

在代码中定义文件选择器

接下来,定义一个Activity来展示内部存储器中files/images/目录下的可用文件,并允许用户来选择需要的文件。下面这段代码演示了如何定义一个Activity来响应用户的选择:

public class MainActivity extends Activity {// The path to the root of this app's internal storageprivate File mPrivateRootDir;// The path to the "images" subdirectoryprivate File mImagesDir;// Array of files in the images subdirectoryFile[] mImageFiles;// Array of filenames corresponding to mImageFilesString[] mImageFilenames;// Initialize the Activity@Overrideprotected void onCreate(Bundle savedInstanceState) {...// Set up an Intent to send back to apps that request a filemResultIntent =new Intent("com.example.myapp.ACTION_RETURN_FILE");// Get the files/ subdirectory of internal storagemPrivateRootDir = getFilesDir();// Get the files/images subdirectory;mImagesDir = new File(mPrivateRootDir, "images");// Get the files in the images subdirectorymImageFiles = mImagesDir.listFiles();// Set the Activity's result to null to begin withsetResult(Activity.RESULT_CANCELED, null);/** Display the file names in the ListView mFileListView.* Back the ListView with the array mImageFilenames, which* you can create by iterating through mImageFiles and* calling File.getAbsolutePath() for each File*/...}...
}

响应文件选择器

一旦用户选择了被共享的文件,你的程序必须检查哪一个文件被选中,并且生成该文件的URI地址。前面的部分Activity在ListView中展示了可用的文件列表,当用户点击了文件的名称,随之系统会调用方法onItemClick(),在这个方法中你可以获取到被选中的文件。

在onItemClick()方法中,从被选择的文件中获得文件的File对象,然后将这个对象作为参数传递给getUriForFile(),它会伴随着权限一并加入,这个权限是由 < provider>元素指定的。结果URI会包含权限、文件在相应目录中的路径段(在XML meta-data中指定的部分)以及文明的名称和其扩展部分。有关FileProvider如何映射meta-data与路径段的目录,请看章节Specify Sharable Directories。

下面的代码段展示了如何检测被选择的文件以及获取该文件的URI:

    protected void onCreate(Bundle savedInstanceState) {...// Define a listener that responds to clicks on a file in the ListViewmFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Override/** When a filename in the ListView is clicked, get its* content URI and send it to the requesting app*/public void onItemClick(AdapterView<?> adapterView,View view,int position,long rowId) {/** Get a File for the selected file name.* Assume that the file names are in the* mImageFilename array.*/File requestFile = new File(mImageFilename[position]);/** Most file-related method calls need to be in* try-catch blocks.*/// Use the FileProvider to get a content URItry {fileUri = FileProvider.getUriForFile(MainActivity.this,"com.example.myapp.fileprovider",requestFile);} catch (IllegalArgumentException e) {Log.e("File Selector","The selected file can't be shared: " +clickedFilename);}...}});...}

要记住,你只可以对在< paths>元素中指定目录下的文件进行URI编码,就像Specify Sharable Directories这节课中描述的一样。如果你对getUriForFile()方法中传入的File参数并没有在< path>元素中指定,那么你会收到一个 IllegalArgumentException异常。

对文件授予权限

现在对将要分享的文件有了一个URI,你需要允许客户端APP来访问这个文件。为了允许访问,需要通过添加URI到一个Intent上,并且在这个Intent上设置权限标志。产生的这个权限是个临时权限,并且会在接收端APP任务结束的时候自动终止。

下面这段代码展示了如何对文件设置读取权限:

    protected void onCreate(Bundle savedInstanceState) {...// Define a listener that responds to clicks in the ListViewmFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView,View view,int position,long rowId) {...if (fileUri != null) {// Grant temporary read permission to the content URImResultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);}...}...});...}

Caution:安全的对文件授予临时访问权限,setFlags()是唯一的方式。要避免对文件的URI使用Context.grantUriPermission()方法,因为该方法授予的权限只可以通过Context.revokeUriPermission()方法撤销。

对客户端APP共享文件

如果要共享文件给客户端APP,需要传递一个Intent给setResult(),这个Intent包含了文件的URI以及访问权限。当你定义的这个Activity结束时,系统会发送这个Intent给客户端APP,下面这段代码展示了如何实现这部分功能:

    protected void onCreate(Bundle savedInstanceState) {...// Define a listener that responds to clicks on a file in the ListViewmFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView,View view,int position,long rowId) {...if (fileUri != null) {...// Put the Uri and MIME type in the result IntentmResultIntent.setDataAndType(fileUri,getContentResolver().getType(fileUri));// Set the resultMainActivity.this.setResult(Activity.RESULT_OK,mResultIntent);} else {mResultIntent.setDataAndType(null, "");MainActivity.this.setResult(RESULT_CANCELED,mResultIntent);}}});

一旦用户选择了文件,那么就应该立即带用户返回客户端APP。实现这种方式的一种方法就是提供一个钩形符号或者结束按钮。使用Button的android:onClick属性与对应的Button相关联。在方法中。调用finish()方法:

    public void onDoneClick(View v) {// Associate a method with the Done buttonfinish();}

Android官方开发文档Training系列课程中文版:分享文件之分享一个文件相关推荐

  1. Android官方开发文档Training系列课程中文版:目录

    原文地址 : http://android.xsoftlab.net/training/index.html 引言 在翻译了一篇安卓的官方文档之后,我觉得应该做一件事情,就是把安卓的整篇训练课程全部翻 ...

  2. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  3. Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制

    原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html 如果你还不清楚如何定义图形及坐标系统,请移步:Android官方 ...

  4. Android官方开发文档Training系列课程中文版:使用Fragment构建动态UI之Fragment创建

    原文地址:http://android.xsoftlab.net/training/basics/fragments/index.html 导言 为了在Android中创建动态的多面板用户界面,你需要 ...

  5. Android官方开发文档Training系列课程中文版:分享文件之配置文件共享

    原文地址:http://android.xsoftlab.net/training/secure-file-sharing/index.html 导言 APP经常需要给其它的APP提供一个或多个文件. ...

  6. Android官方开发文档Training系列课程中文版:打印内容之HTML文档打印

    原文地址:http://android.xsoftlab.net/training/printing/html-docs.html 在Android中打印内容要比打印照片要复杂一些,它要求将文本与图像 ...

  7. Android官方开发文档Training系列课程中文版:动画视图之应用场景

    原文链接:http://android.xsoftlab.net/training/transitions/transitions.html 在转场框架中,动画是由一帧帧的图像连续绘制形成的,这一帧帧 ...

  8. Android官方开发文档Training系列课程中文版:管理音频播放之控制APP的音量与播放

    原文地址:http://android.xsoftlab.net/training/managing-audio/index.html 引言 如果APP需要播放音频,允许用户可以控制音频的播放状态是很 ...

  9. Android官方开发文档Training系列课程中文版:分享文件之获取文件信息

    原文地址:http://android.xsoftlab.net/training/secure-file-sharing/retrieve-info.html 之前的课程讲述了客户端APP试图与含有 ...

最新文章

  1. keil 函数 默认 外部 内部 博客_5.9 C++内部函数与外部函数
  2. 注入游戏没有焦点_数独游戏 数学之美(三)
  3. wxWidgets:wxDragImage 示例
  4. CSharp关键字----using
  5. java 生成校验验证码_java生成验证码并进行验证
  6. 计算机专业英语的理解,计算机专业英语之理解网络地址
  7. PHP Reflection与依赖注入
  8. var和function谁先优先执行_浅谈JavaScript 的执行顺序
  9. 前端js实现打印excel表格
  10. 如何删减QQ无用功能 为系统彻底减负
  11. c 易语言置入代码6,易语言置入代码动态版
  12. 神经网络与机器学习导言笔记——反馈
  13. 【Python】使用Python批量移动文件
  14. python滚动广告牌,Discovery Live 参数化建模案例-设计广告牌风场选址
  15. 15版计算机应用基础知识整理,[电脑基础知识]计算机应用基础.ppt
  16. 如何找到算法的时间复杂度
  17. 深入浅出Android性能调优,震撼来袭免费下载!
  18. oracle 虚拟表 多行,Oracle使用虚拟表dual一次插入多条记录【摘录】
  19. 专业计算机基础教学,计算机基础教学计划
  20. 投资转型:实体店铺,投资经营复盘

热门文章

  1. 计算机沟通方式,雅思阅读练习:计算机改变沟通方式
  2. gps84转换gcj02公式_百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换...
  3. C语言中的转义字符【转ce123的技术博客】
  4. html导出pdf实例,jsPDF导出pdf示例
  5. 十三、Vuex学习笔记
  6. 论文阅读 - AUTOVC: Zero-Shot Voice Style Transfer with Only Autoencoder Loss
  7. LeetCode 1992. 找到所有的农场组(BFS)
  8. 04.卷积神经网络 W2.深度卷积网络:实例探究(作业:Keras教程+ResNets残差网络)
  9. LeetCode MySQL 597. 好友申请 I :总体通过率
  10. LeetCode 346. 数据流中的移动平均值(队列)