Develop -- Training(十) -- 共享文件

设置文件共享

通过 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)));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值