介绍:这里只是我的使用 只是一个思路而已 遇到一个需求需要共享私有目录的文件,供其他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