FileProvider 和 ContentProvider 联合使用

介绍:这里只是我的使用 只是一个思路而已  遇到一个需求需要共享私有目录的文件,供其他APP使用。不能跳转获取,我看网上大部分说FileProvider 的使用都是通过Intent 跳转 在 onActivityResult() 方法获取返回的Uri。本方法主要利用的是ContentProvider 来对外提供方法使用。还利用Uri 本身可以使用String 相互转换。

FileProvider的使用 

1、注册

<manifest>
    ...
    <application>
        ...
     <provider
          android:name="android.support.v4.content.FileProvider" //provider的类名
            android:authorities="com.example.wlj.fileproviderdemo" //没有特定要求,自定义
            android:exported="false"           //不建议设置未true
            android:grantUriPermissions="true">  //允许你有给其赋予临时访问权限的权力

    <meta-data
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/file_paths" />
     </provider>

     <provider
         android:name=".TestContentProvider"
         android:authorities="com.example.wlj.fileproviderdemo.testContentProvider"
         android:exported="true" />  //当前内容提供者是否会被其它应用使用

     ...
    </application>
</manifest>
这里是直接使用的v4包中的FileProvider,我们也可以直接继承FileProvider类,适当重写重载函数,但不建议如此做。下面来介绍上面的几个设置:

    name:provider的类名,若使用默认的v4的FileProvider可使用”android.support.v4.content.FileProvider”,也可以设置为自定义的继承FileProvider的provider类;
    authorities:一个签名认证,可以自定义,但在获取uri的时候需要保持一致;
    grantUriPermissions:使用FileProvider的使用需要我们给流出的URI赋予临时访问权限(READ和WRITE),该设置是允许我们行使该项权力;
    meta-data:meta-data配置的是我们可以访问的文件的路径配置信息,需要使用xml文件进行配置,FileProvider会通过解析xml文件获取配置项,其中name名字不可改变为:android.support.FILE_PROVIDER_PATHS,resource为配置路径信息的配置项目。

2、路径配置

可访问的路径配置可以在res中建立一个xml文件下面建立一个配置文件,格式如下:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <cache-path path="themes" name="themes" />
</paths>
<files-path/>代表的根目录: Context.getFilesDir()
<external-path/>代表的根目录: Environment.getExternalStorageDirectory()

<cache-path/>代表的根目录: getCacheDir()

3、使用

先将一个文件写入私有目录

package com.example.wlj.fileproviderdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class MainActivity extends AppCompatActivity {

    public static final String PATH = "/data/user/0/com.example.wlj.fileproviderdemo/cache/themes/test.png";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        File file = new File(PATH);
        Log.e("AAA-->", "onCreate: " + file.getPath());
        try {
            InputStream inputStream = getAssets().open("main.png");
            writeFile(inputStream,file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
// 写入文件
    private static void writeFile(InputStream in, File file) throws IOException {
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
        byte[] buffer = new byte[8192];
        int read;

        while (-1 != (read = in.read(buffer))) {
            out.write(buffer, 0, read);
        }
        in.close();
        out.close();
    }
}

由ContentProvider向外提供方法对外使用

package com.example.wlj.fileproviderdemo;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.util.Log;

import java.io.File;

/**
 * Created by wlj on 18-4-13.
 */

public class TestContentProvider extends ContentProvider {
    private static final String FILE_AUTHORITY = "com.example.wlj.fileproviderdemo"; // 和清单文件注册的一样  FileProvider

    private static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private static final String AUTHORITY = "com.example.wlj.fileproviderdemo.testContentProvider"; // 和注册的一样  TestContentProvider
    private static final int WALLPAPER = 9;

    static {
        sUriMatcher.addURI(AUTHORITY, "/wallpaper/small/*", WALLPAPER);
    }

    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        Log.e("AAA-->", "getType: " + uri.toString() );
        int match = sUriMatcher.match(uri);
        String packageName = null;
        switch (match) {
            case WALLPAPER:
                packageName = uri.getLastPathSegment();
                break;
        }
        // 将文件的Uri 以 String传递出去
        return getFileUri(packageName, MainActivity.PATH).toString();
    }

    // 获取文件Uri 地址
    private Uri getFileUri(String packageName, String path) {
        Uri uri;
        uri = FileProvider.getUriForFile(getContext(), FILE_AUTHORITY,
                new File(path));

        granUriPermission(getContext(), packageName, uri);
        return uri;
    }

    // 赋予临时权限
    private void granUriPermission(Context context, String packageName, Uri uri) {
        context.grantUriPermission(packageName, uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }


    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}

在其他APP 调用getContentResolver()

package com.example.wlj.fileproviderclientdemo;

import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ImageView;

import java.io.FileNotFoundException;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = ((ImageView) findViewById(R.id.main_vi));
        String serviceStr = "com.example.wlj.fileproviderdemo.testContentProvider"; // service 内容提供者
        Uri uri = Uri.parse("content://" + serviceStr + "/wallpaper/small/"
                + getPackageName());
        String uriString = getContentResolver().getType(uri);

        Log.e("AAA-->", "onCreate: " + uriString );
        readFile(Uri.parse(uriString));
    }

    private void readFile(Uri returnUri) {
        ParcelFileDescriptor inputPFD;
        //获取文件句柄
        try {
            inputPFD = getContentResolver().openFileDescriptor(returnUri, "r");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }
        //获取文件名字和大小
        Cursor returnCursor =
                getContentResolver().query(returnUri, null, null, null, null);
        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
        returnCursor.moveToFirst();
        Log.e("AAA-->", "readFile: " + "文件名:" + returnCursor.getString(nameIndex) + ", 大小:" +
                Long.toString(returnCursor.getLong(sizeIndex)) + " B");
        returnCursor.close();

        Bitmap bitmap = BitmapFactory.decodeFileDescriptor(inputPFD.getFileDescriptor());
        iv.setImageBitmap(bitmap);

        try {
            inputPFD.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这就是我整个使用FileProvider 一个使用思路   欢迎大神指点。

service 的Demo https://github.com/wlj1627846329/FileProviderDemo

client 的Demo FileProviderClientDemo

猜你喜欢

转载自blog.csdn.net/wljian1/article/details/79885107
今日推荐