Develop -- Training(十) -- 共享文件
2016-03-06 16:02
489 查看
设置文件共享
通过 FileProvider 来设置文件共享, FileProvider 是在 v4 的支持库中的。指定 FileProvider
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application ...> <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.myapp.fileprovider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" /> </provider> ... </application> </manifest>
在 manifest 清单文件中添加 provider 节点元素,指定 FileProvider 类。
android:authorities 属性:指定权威的 URI 通过 FileProvider 来生成你想要的 URIs 的内容。
一般情况 android:authorities 的组成: 包名 + fileprovider 来组成的
< meta-data > 里的 android:name 属性:指向指定要共享的目录的XML文件
< meta-data > 里的 android:resource 属性:是文件的路径和名称
指定可共享目录
在 res/xml/ 目录下创建 filepaths.xml 文件
<paths> <files-path path="images/" name="myimages" /> </paths>
< files-path > 标签分享的目录是在应用程序的内部存储的 files/ 目录
path 属性:共享 files/ 下的 images/ 子目录
name 属性:告诉 FileProvider 在 files/images/ 子目录下添加路径段 myimages 内容的URI中的文件
注意: XML 文件是唯一可以指定要共享的目录,不能以编程方式添加目录。
content://com.example.myapp.fileprovider/myimages/default_image.jpg
共享文件(相当于服务器端)
通过 startActivityForResult() 中的 intent 包含着 ACTION_PICK 来传递数据。设置一个可以选择的 Activity,意图过滤器要匹配 ACTION_PICK,类别是 CATEGORY_DEFAULT 和 CATEGORY_OPENABLE,也可以选择指定 MIME Type。
<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 的返回 code
public class MainActivity extends Activity { // The path to the root of this app's internal storage private File mPrivateRootDir; // The path to the "images" subdirectory private File mImagesDir; // Array of files in the images subdirectory File[] mImageFiles; // Array of filenames corresponding to mImageFiles String[] mImageFilenames; // Initialize the Activity @Override protected void onCreate(Bundle savedInstanceState) { ... // Set up an Intent to send back to apps that request a file mResultIntent = new Intent("com.example.myapp.ACTION_RETURN_FILE"); // Get the files/ subdirectory of internal storage mPrivateRootDir = getFilesDir(); // Get the files/images subdirectory; mImagesDir = new File(mPrivateRootDir, "images"); // Get the files in the images subdirectory mImageFiles = mImagesDir.listFiles(); // Set the Activity's result to null to begin with setResult(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 mResultIntent.addFlags (Intent.FLAG_GRANT_READ_URI_PERMISSION );
注意:调用setFlags()是安全地访问权限授予使用临时访问权限文件的唯一途径。避免调用 Context.grantUriPermission()的文件的内容URI的方法,因为这种方法授予访问,你只能通过调用撤销Context.revokeUriPermission() 。
请求共享文件(相当于客户端)
通过 startActivityForResult() 来请求,然后通过 onActivityResult()来处理请求结果。public class MainActivity extends Activity { private Intent mRequestFileIntent ; private ParcelFileDescriptor mInputPFD ; ... @Override protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView ( R . layout . activity_main ); mRequestFileIntent = new Intent ( Intent . ACTION_PICK ); mRequestFileIntent . setType ( "image/jpg" ); ... } ... protected void requestFile () { /** *当用户请求一个文件时,发送意向到 *服务器应用程序。 *文件。 * / startActivityForResult (mRequestFileIntent , 0 ); ... } ... } @Override public void onActivityResult(int requestCode, int resultCode, Intent returnIntent) { // If the selection didn't work if (resultCode != RESULT_OK) { // Exit without doing anything else return; } else { // Get the file's content URI from the incoming Intent Uri returnUri = returnIntent.getData(); /* * Try to open the file for "read" access using the * returned URI. If the file isn't found, write to the * error log and return. */ try { /* * Get the content resolver instance for this context, and use it * to get a ParcelFileDescriptor for the file. */ mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r"); } catch (FileNotFoundException e) { e.printStackTrace(); Log.e("MainActivity", "File not found."); return; } // Get a regular file descriptor for the file FileDescriptor fd = mInputPFD.getFileDescriptor(); ... } }
该方法openFileDescriptor() 返回一个ParcelFileDescriptor该文件。从这个对象,客户端应用程序获取一个的FileDescriptor对象,它可以再使用读取文件。
获取文件信息
判断文件的 MIME Type 类型/* * Get the file's content URI from the incoming Intent, then * get the file's MIME type */ Uri returnUri = returnIntent.getData(); String mimeType = getContentResolver().getType(returnUri);
查询文件的名称和大小, FileProvider 有个 query() 可以查询出文件的相关信息。
DISPLAY_NAME:返回 String 类型。文件名称。
SIZE:返回 Long 类型。文件大小。
/* * Get the file's content URI from the incoming Intent, * then query the server app to get the file's display name * and size. */ Uri returnUri = returnIntent.getData(); Cursor returnCursor = getContentResolver().query(returnUri, null, null, null, null); /* * Get the column indexes of the data in the Cursor, * move to the first row in the Cursor, get the data, * and display it. */ int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE); returnCursor.moveToFirst(); TextView nameView = (TextView) findViewById(R.id.filename_text); TextView sizeView = (TextView) findViewById(R.id.filesize_text); nameView.setText(returnCursor.getString(nameIndex)); sizeView.setText(Long.toString(returnCursor.getLong(sizeIndex)));
相关文章推荐
- Failed to extend swap file from 0 kb to xxx kb.
- 理解int main(int argc,char **argv)中的参数的意义
- 进程等待示例(wait与waitpid调用)
- 源码阅读笔记 – 2 std::vector (2) 关于Allocator Aware Container特性
- HDU 1104 Remainder
- 笔记:batch normalization:accelerating deep network training by reducing internal covariate shift
- 关于vsftp出现Restarting vsftpd (via systemctl): Job for vsftpd.service failed because the control 的解决办法
- 理解setRetainInstance
- Tencent qmail 的一个漏洞
- EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS的删除创建
- hdu 5288 ZCC loves straight flush
- 利用python aiohttp编写web框架
- 遇到的retain cycle例子
- Adb failed to restart! Make sure the plugin is properly configured.
- saiku 无密码登陆
- Daivik VM 和 JVM 的比较
- network namespace与veth pair
- POJ-1230 Pass-Muraille
- Xcode7 发布应用 Failed to locate or generate matching signing assets
- Climbing Stairs