IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> ContentProvider 实战 -> 正文阅读

[移动开发]ContentProvider 实战

近期项目中需要从一个应用中拷贝一份文件(该文件无法直接拿到),并且文件放置的目录是data下,外部应用无法直接访问,所以考虑使用ContentProvider来实现。

ContentProvider,Android四大组件;ContentProvider 的作用是为不同的应用之间数据共享,提供统一的接口。本文就主要来说下实现样例。

一. 新建项目。相信大家都会了。

新建了两个项目,test01和test02。实例如下:

最终实现从test01的data目录下拷贝文件(data.xml)至test02中。

二.自定义实现ContentProvider。下面是代码展示:

/**
 * 文件共享
 */
public class FileContentProvider extends ContentProvider {

    final private static String TAG = "FileContentProvider";
    //文件名称
    private static String FILENAME = "data.xml";


    @Override
    public boolean onCreate() {
        Log.d(TAG, "========= onCreate is called =========");
        return true;
    }

 
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        Log.d(TAG, "========= query is called selection =========> " + selection);

        return null;
    }


    /**
     * 获取文件的文件名
     *
     * @param uri
     * @return
     */
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        //判断文件是否存在
        String fileName = "";
        String path = MyApp.getContext().getFilesDir().getAbsolutePath();
        if (TextUtils.isEmpty(path)) {
            Log.i(TAG, "Data path must not be null!");
            ToastUtils.s(MyApp.getContext(), "Data path must not be null! ");
            fileName = "";
            return fileName;
        }
        File datapathFile = new File(path);
        if (!datapathFile.exists()) {
            Log.i(TAG, "Data path does not exist!");
            ToastUtils.s(MyApp.getContext(), "Data path does not exist! ");
            fileName = "";
            return fileName;
        }
        File datafile = new File(path + File.separator +
                FILENAME);
        if (!datafile.exists()) {
            Log.i(TAG, "Data file not found at " + datafile);
            ToastUtils.s(MyApp.getContext(), "Data file not found at " + datafile);
            fileName = "";
            return fileName;
        }
        fileName = FILENAME;
        Log.i(TAG, "fileName:" + FILENAME);
        Log.i(TAG, "uri.getPath():" + uri.getPath());
        return fileName;
    }

    @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;
    }


    /**
     * 需要实现该方法,
     *
     * @param uri
     * @param mode
     * @return
     * @throws FileNotFoundException
     */
    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
            throws FileNotFoundException {
        String fileName = FILENAME;
        String filePath = MyApp.getContext().getFilesDir().getAbsolutePath() + File.separator + fileName;
        //如果存在文件,则获取文件相关信息,并返回
        File datafile = new File(filePath);
        if (datafile.exists()) {
            Log.i(TAG, " fileName: " + fileName);
            Log.i(TAG, "filePath: " + filePath);
            //计算文件的md5
            Log.i(TAG, "文件 file2MD5 " + Md5CaculateUtil.file2MD5(datafile));
            return ParcelFileDescriptor.open(datafile,
                    ParcelFileDescriptor.MODE_READ_ONLY);
        } else {
            Log.d(TAG, "file not found at" + filePath);
            return null;
        }
    }


}

?说明:

1.重写了两个方法;

2.getType()方法 返回文件名称,openFile()方法返回文件流;

三. test01其他实现代码。

  private void goToTest02() {
        if (AppUtil.checkAppInstalled(MainActivity.this, SLF_PACKAGE_NAME)) {
            getFile();
        } else {
            ToastUtils.s(MainActivity.this, "应用未安装");
        }
    }

    /**
     * 获取文件
     */
    private void getFile() {
        Intent intent = new Intent();
        ComponentName componeneName = new ComponentName(SLF_PACKAGE_NAME, SLF_ACTIVITY_NAME);
        intent.setComponent(componeneName);
        String filePath = MyApp.getContext().getFilesDir().getAbsolutePath() + File.separator + FILENAME;
        //如果存在文件,则获取文件的相关信息,并返回
        File datafile = new File(filePath);
        if (datafile.exists()) {
            Log.d(TAG, "文件存在");
            Log.i(TAG, " fileName: " + FILENAME);
            Log.i(TAG, "filePath: " + filePath);
            //计算文件的md5
            Log.i(TAG, "文件 file2MD5 " + Md5CaculateUtil.file2MD5(datafile));
            String fileSize = FileSizeUtil.getAutoFileOrFilesSize(filePath);
            Log.d(TAG, "文件的大小- fileSize is " + fileSize);
            intent.putExtra("fileName", FILENAME);
            startActivity(intent);
            return;
        }
        Log.d(TAG, "文件不存在");
        ToastUtils.s(MyApp.getContext(), "file not found at " + FILENAME);
    }

说明:

1. 先判断是否安装了test02应用;

2.判断是否存在需要共享的文件;

四. test02 部分实现代码,

   /**
     *
     */
    private void getFileFromOutside() {
        Intent data = getIntent();
        if (data != null) {
            String fileName = data.getStringExtra("fileName");
            if (!TextUtils.isEmpty(fileName)) {
                Log.i(TAG, " fileName: " + fileName);
                readFile(fileName);
            } else {
                Log.i(TAG, "文件名未传递,请先核查是否有文件");
            }
        } else {
            Log.i(TAG, "getIntent() is null");
        }
    }

    /**
     * 通过getContentResolver 读取文件
     *
     * @param fileName
     */
    private void readFile(String fileName) {
        String filePath = getFilesDir().getAbsolutePath() + File.separator + fileName;
        File datafile = new File(filePath);
        //文件是否已经存在;如果存在,则不用再获取
        if (datafile.exists()) {
            Log.d(TAG, "file is exists");
            String fileSize = FileSizeUtil.getAutoFileOrFilesSize(filePath);
            Log.d(TAG, "文件的大小- fileSize is " + fileSize);
            //计算文件的md5
            Log.i(TAG, " 文件 file2MD5 " + Md5CaculateUtil.file2MD5(new File(filePath)));
            ToastUtils.s(MainActivity.this, "file is exists");
            return;
        }
        try {
            //通过contentprovide 获取文件名
            fileName = getContentResolver().getType(mUrl);
            if (TextUtils.isEmpty(fileName)) {
                Log.i(TAG, "fileName is null");
                return;
            }
            //通过contentprovide 获取文件
            InputStream is = getContentResolver().openInputStream(mUrl);
            // 获取文件路径
            filePath = getFilesDir().getAbsolutePath() + File.separator + fileName;
            OutputStream os = new FileOutputStream(new File(filePath));
            byte[] b = new byte[1024];
            int len;
            while ((len = is.read(b)) != -1) {
                os.write(b, 0, len);
            }
            os.flush();
            is.close();
            os.close();
            // 计算拷贝文件大小
            String fileSize = FileSizeUtil.getAutoFileOrFilesSize(filePath);
            Log.d(TAG, "-导入的 文件的大小- fileSize is " + fileSize);
            //计算文件的md5
            Log.i(TAG, "文件  file2MD5 " + Md5CaculateUtil.file2MD5(new File(filePath)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

说明:

1.先判断文件是否存在;

2.调用ContentProvider提供的方法,从文件流中获取需要共享的文件,写入test02应用中。

3.其他代码详见源码。

4.上传文件“data.xml”至目录“/data/data/com.demo.test01/files”下。

5.运行后,日志,

?

test01和test02 源码和apk 下载地址

五. 总结。

使用ContentProvider来达到应用见数据共享,需要自定义ContentProvider,重写相关方法;然后在应用中调用ContentProvider提供的外部调用方法。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 08:05:55  更:2021-09-19 08:06:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:00:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码