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