Android_09_自定义内容提供者及访问内容提供者

前言:

内容提供者是安卓应用程序的主要基石之一,其目的是为应用程序提供内容。它们封装数据,然后通过一个ContentResolver接口

将封装的数据提供给应用程序;如果你想要在多个应用中去共享数据,那么只需要一个内容提供者就可以了;例如:联系人的数据

是被多个应用所共享的,所以这个数据必须存储在一个内容提供者中;如果你不想在多个应用中去共享这个数据,那么你可以

通过SQLite数据库来实现;

当通过一个ContentResolver来发送一个请求时,系统会检查这个给定的URI的权限,然后将这个URI传递给这个内容提供者,只要内容

提供者想要的话,内容提供者是可以解析剩余的URI的;UriMatcher有助于去解析URI;


以下是一些需要被实现的方法:

onCreate():当初始化一个provider的时候,这个方法就会被调用;

query(Uri, String[], String, String[], String):这个是用来返回数据给调用者;

insert(Uri, ContentValues):这个是用来插入数据到内容提供者中;

update(Uri, ContentValues, String, String[]):更新内容提供者中的数据;

delete(Uri, String, String[]):删除内容提供者中的数据;

getType(Uri):在内容提供者中返回一个MIME类型的数据;


Note:

数据访问的方法(insert(Uri, ContentValues)和update(Uri, ContentValues, String, String[])),同一时刻,也许会被多个线程所调用,

所以在使用时应该注意一下其线程安全的问题;其他的方法(比如:onCreate())则只会被应用的主线程调用,所以在这里必须去避免

一些耗时的操作;


本示例的演示的是:

在自定义的内容提供者这个应用的MainActivity中写入一个文件,与此同时,并这个应用中提供一个内容提供者,

供其他应用程序通过这个内容提供者去访问这个应用的文件

在访问内容提供者的应用中,通过获取ContentResolver对象来向自定义内容提供者应用的文件写入数据;以此来达到

学习内容提供者的目的;


代码示例如下:

自定义内容提供者

MainActivity.java

package com.example.administrator.testascontentprovider;

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

import java.io.File;
import java.io.IOException;

/***
 * 在本示例中,我们先让这个应用生成一个文件,然后
 * 通过外部应用借助本应用的ContentProvider来实现
 * 对本应用文件的写入操作;
 * ***/
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            /***
             * 1>
             * new File()的时候,若文件不存在,其并不会去闯进一个文件,
             * 此时需要调用file.create()来创建这个文件;
             * 2>
             * getFilesDir()是在本应用的目录下去创建文件,如这个示例所示,
             * 其所创建的文件的路径如下:
             * /data/data/com.example.administrator.testascontentprovider/files/Content.txt
             *
             * 3>
             * 在操作SD卡时,记得其相应权限的添加
             * **/
            File file = new File(getFilesDir(),"Content.txt");
            if(file.exists()){
                Log.e("file","exist");
            }else {
                try {
                    file.createNewFile();
                    if(file.exists()){
                        Log.e("file",file.getAbsolutePath());
                    }else {
                        Log.e("file","create failed");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}


MyContentProvider.java

package com.example.administrator.testascontentprovider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;

/***
 * 在本示例中,这个ContentProvider的作用是:
 * 充当一个媒介的作用,因为外面的应用没法访问
 * 本应用内部的文件,所以在本应用中增加这个
 * ContentProvider是为了能够让外界通过
 * ContentProvider来访问本应用中的某些
 * 想要暴漏的数据文件;
 *
 * 在本示例中,我们仅仅测试文件的插入操作;
 * 若对于其他操作,也想实现,可自己单独去
 * 重写相应的方法;
 * **/
public class MyContentProvider extends ContentProvider {
    public MyContentProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    /****
     * 在本示例中,我们仅实现对文件内容的写入操作;
     *
     * uri:是我们本应用的ContentProvider的地址,
     * 也就是我们在AndroidManifest.xml中声明的
     * android:authorities="testContentProvider"
     *
     * values:是外部应用传入的数据
     * **/
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        /***
         * values写入本应用的文件中;
         * ***/
        String string = (String) values.get("test");
        Log.e("string",string);
        File file = new File(getContext().getFilesDir(),"Content.txt");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(string.getBytes());
        } catch (Exception e) {
            Log.e("write","");
            e.printStackTrace();
        }
        return uri;
    }

    @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.testascontentprovider">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name=".MyContentProvider"
            android:authorities="testContentProvider"
            android:enabled="true"
            android:exported="true"></provider>
    </application>

</manifest>

访问内容提供者

MainActivity.java

package com.example.administrator.testaccesscontentprovider;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

/**
 * 本应用的目的是:向有ContentProvider的应用TestAsContentProvider
 * 写入数据
 * **/
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /***
     * ContentProvider写入数据
     * ***/
    public void insert(View view){
        ContentResolver contentResolver = getContentResolver();
        ContentValues contentValues = new ContentValues();
        contentValues.put("test","hello world");
        /***
         * 记得加上URI的前缀:content://
         * **/
        contentResolver.insert(Uri.parse("content://testContentProvider"),contentValues);
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.testaccesscontentprovider.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="insert"
        android:onClick="insert"
        />
</RelativeLayout>


运行结果如下:



总结:

内容提供者的作用是让应用去暴漏部分数据,以供其他应用去操作;

内容提供者存在于想要暴漏数据的应用中,目的是为其他应用通过内容提供者去访问这个数据;


源码:

1>

自定义内容提供者源码

2>

访问内容提供者源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值