Android内容提供器

简介

内容提供器主要用于在不同应用程序之间实现数据共享的功能,他可以选择只对那一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。
例子:微信读取手机联系人信息

一.创建自己的内容提供器

一个app只有创建了自己的内容提供器,才能让别的程序去访问他共享的数据
1. 创建一个SQL数据库
要使用内容提供器肯定需要程序中有SQL数据库,这里只是简单的创建出来做个演示,可以用SQLiteDatabase创建,也可以用LitePal,不懂的点这里,我用LitePal创建了一个Demo库,litepal.xml和Demo1表如下
<?xml version="1.0" encoding="UTF-8" ?>
<litepal>
   <dbname value="demo"/>
   <version value="1"/>
   <list>
       <mapping class="com.example.revise_sqlitedatabase.Demo1"></mapping>
   </list>
</litepal>
package com.example.revise_sqlitedatabase;

import org.litepal.crud.LitePalSupport;
public class Demo1 extends LitePalSupport {
    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2. 创建自己的内容提供器
右击包名->new->Other->ContentProvider

在这里插入图片描述

class name就是你的内容提供器的类名,URI Authorities就是URI的authority,一般写成 包名.provider
URI:给内容提供器中的数据建立了唯一的标识符,就是根据他知道要访问那个数据,由两部分组成:authority(上面创建时的URI Authorities),path(表名,访问那张表就写啥比如/table),为了看出这是URI还要加上头部协议,标准格式如下
content://com.example.app.provider/table
接下来吧URI解析成Uri对象,用Uri做参数就可以访问数据了
Uri uri = uri.parse(content://com.example.app.provider/table)
我的内容提供器如下,方法中的uri就是别的程序在调用时传入的,可根据他做出对应的操作
package com.example.revise_sqlitedatabase;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

import org.litepal.LitePal;

public class MyContentProvider extends ContentProvider {
    public static final int Demo1_DIR = 0;          //访问所有数据
    public static final int Demo1_ITEM = 1;        //访问单条数据
    public static final String AUTHORITY=  "com.example.revise_sqlitedatabase.provider";
    private static UriMatcher uriMatcher;
    private Demo1 demo1;
    SQLiteDatabase db;			
	/*
	UriMatcher类可看做匹配URI的工具类,
	addURI方法传入authority,path,和一个自定义代码
	当调用UriMatcher的match()方法时,可根据传入的uri返回相应的自定义代码 
	用自定义代码去判断到底访问的是那个表
	*/
    static{
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY,"Demo1",Demo1_DIR);
        uriMatcher.addURI(AUTHORITY,"Demo1/#",Demo1_ITEM);//#匹配数字
    }
    public MyContentProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
    //删除数据
        int deletedRows = 0;
        switch (uriMatcher.match(uri)){
            case Demo1_DIR:
                deletedRows = db.delete("Demo1",selection,selectionArgs);    //返回受影响的行数
                break;
            case Demo1_ITEM:
                String Id = uri.getPathSegments().get(1);
                //getPathSegments()方法吧URI权限后的部分以“/”分割,0位置是路径,1位置是id
                deletedRows = db.delete("Demo1","id = ?",new String[]{Id});
                break;
            default:
                break;
        }
        return deletedRows;
    }

    @Override
    public String getType(Uri uri) {
    /*
    返回Uri对象所对应的MIME类型,三部分组成
    1.以vnd开头
    2.如果URI以路径结尾,后接android.cursor.dir/,如果以id结尾,后接android.cursor.item/
    3.最后接上vnd.<authority>.<path>
    */
        switch (uriMatcher.match(uri)){
            case Demo1_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.revise_sqlitedatabase.Demo1";
            case Demo1_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.revise_sqlitedatabase.Demo1";
            default:
                break;
        }
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
    //添加数据返回的是新添加的数据的Uri
        Uri uriReturn = null;
        switch (uriMatcher.match(uri)){
            case Demo1_DIR:
            case Demo1_ITEM:
                long newId = db.insert("Demo1",null,values);
                uriReturn = Uri.parse("content://"+AUTHORITY+"/Demo1/"+newId);
                break;
            default:
                break;
        }
        return uriReturn;
    }

    @Override
    public boolean onCreate() {
    //获取SQLiteDatabase因为这些方法全是用SQLiteDatabase访问数据库的
        db = LitePal.getDatabase();		
       return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
         //查询数据返回Cursor            
        Cursor cursor = null;
        switch (uriMatcher.match(uri)){
            case Demo1_DIR:
                cursor = db.query("Demo1",projection,selection,selectionArgs,null,null,sortOrder);
                break;
            case Demo1_ITEM:
                String Id = uri.getPathSegments().get(1);
                cursor = db.query("Demo1",projection,"id = ?",new String[]{Id},null,null,sortOrder);
                break;
            default:
                break;
        }
        return cursor;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
          //更新数据            
        int updatedRows = 0;
        switch (uriMatcher.match(uri)){
            case Demo1_DIR:
               updatedRows = db.update("Demo1",values,selection,selectionArgs);     //返回受影响的行数
                break;
            case Demo1_ITEM:
                String Id = uri.getPathSegments().get(1);
                updatedRows = db.update("Demo1",values,"id = ?",new String[]{Id});
                break;
            default:
                break;
        }
        return updatedRows;
    }
}

二.访问刚才的程序中的数据

新建一个项目,我的如下,布局文件中有四个按钮,设置点击事件来访问数据
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/add_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add data"/>
    <Button
        android:id="@+id/query_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="query data"/>
    <Button
        android:id="@+id/updata_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Up data"/>
    <Button
        android:id="@+id/delete_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="delete data"/>
</LinearLayout>
package com.example.contentproviderdemotest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private String mewId;
    //把要访问的数据的URI解析成Uri对象
    Uri uri = Uri.parse("content://com.example.revise_sqlitedatabase.provider/Demo1");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button addData = (Button)findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ContentValues values = new ContentValues();
                values.put("name","张三");
                values.put("age",10);
                Uri newUri = getContentResolver().insert(uri,values);
                mewId = newUri.getPathSegments().get(1);            //拿到添加的数据的id
            }
        });
        Button query = (Button)findViewById(R.id.query_data);
        query.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Cursor cursor = getContentResolver().query(uri,null,null,null,null);
                if(cursor!=null){
                    while (cursor.moveToNext()){
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        String age = cursor.getString(cursor.getColumnIndex("age"));
                        Log.d("MainActivity",name);
                        Log.d("MainActivity",age);
                    }
                    cursor.close();        //用完后把cursor关闭
                }
            }
        });
        Button updata = (Button)findViewById(R.id.updata_data);
        updata.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ContentValues values = new ContentValues();
                values.put("name","李四");
                getContentResolver().update(uri,values,null,null);
            }
        });
        Button delete = (Button)findViewById(R.id.delete_data);
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getContentResolver().delete(uri,null,null);
            }
        });


    }
}
运行后打印结果如下

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值