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

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android 中,房间(Room)是一个持久化库,它提供了一种在 SQLite 数据库上进行抽象的方式。它可以帮助你更轻松地管理 SQLite 数据库,同时提供了一些有用的功能,比如类型转换、简单查询、关联查询等。而 ContentProvider 则是一种组件,它可以帮助你在应用程序之间共享数据。 下面是它们的使用方法: 1. Room 的使用: a. 定义实体类:在 Room 中,实体类代表了在数据库中存储的数据表。你需要使用 `@Entity` 注解来标注实体类,并且在其中定义表的列名和类型。 b. 定义 DAO:DAO(数据访问对象)是一个接口,它定义了访问数据库的方法。在 DAO 中,你可以定义增删改查等操作,使用 `@DAO` 注解来标注接口。 c. 定义数据库:你需要定义一个继承自 `RoomDatabase` 类的抽象类,使用 `@Database` 注解来标注。在这个类中,你需要定义数据库的版本号、实体类和 DAO。 d. 使用 Room:在应用程序中,你可以通过创建 `RoomDatabase` 的实例来使用 Room。你可以使用 `Room.databaseBuilder()` 方法来创建数据库,并且使用 `build()` 方法来构建数据库的实例。然后你就可以使用 DAO 中定义的方法来访问数据库了。 2. ContentProvider使用: a. 定义 ContentProvider:你需要继承自 `ContentProvider` 类,并且实现其中的 `query()`、`insert()`、`update()` 等方法。在 ContentProvider 中,你需要定义 URI(统一资源标识符),它代表了数据的位置。使用 `ContentResolver` 类可以访问 ContentProvider。 b. 注册 ContentProvider:在应用程序的 AndroidManifest.xml 文件中,你需要声明你的 ContentProvider使用 `provider` 标签来声明 ContentProvider,并且使用 `android:authorities` 属性来定义 URI。 c. 使用 ContentProvider:在应用程序中,你可以使用 `ContentResolver` 类来访问 ContentProvider。你需要通过 URI 来访问数据,使用 `query()`、`insert()`、`update()` 等方法来进行数据操作。 总的来说,Room 和 ContentProvider 都是 Android 中的持久化库,它们有各自的使用场景。如果你需要在应用程序之间共享数据,或者需要提供数据给其他应用程序使用,那么使用 ContentProvider 是比较合适的。如果你只是需要管理应用程序内部的数据库,那么 Room 是比较合适的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wljian1

你的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值