安卓内容提供者的使用和内容接收的接收

一、整体实现步骤

1. 新建布局文件
2. 建立实体类
3. 建立MySqliteOpenHelpter来帮助我们管理数据库
4. 建立数据库适配器,执行具体的CURD操作
5. 建立内容提供者
6. 在第二个应用中调用第一个应用中的内容(这里没有提到权限的事情)

1.新建布局文件

  1. 效果

    布局文件效果
  2. 布局代码:

  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    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"
    android:orientation="vertical"
    tools:context="cn.jewei.app.privader.MainActivity">

    <Button
        android:onClick="insert"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="增加一条数据" />

    <Button
        android:onClick="update"
        android:text="修改一条数据"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
    <Button
        android:onClick="delete"
        android:text="删除一条数据"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="find"
        android:text="查询单个"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:onClick="findAll"
        android:text="查询所有"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:onClick="createTable"
        android:text="创建数据表"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:onClick="dropTable"
        android:text="删除数据表"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

2.在Activity中先把事件给写上回头再写全


  1. 代码
public class MainActivity extends AppCompatActivity {

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

    //增加数据
    public void insert(View v){
        

    }

    //修改一条数据
    public void update(View v){

    }

    //删除一条数据
    public void delete(View v){

    }

    //查询单个
    public void find(View v){

    }

    //查询所有
    public void findAll(View v){

    }

    //创建数据表
    public void createTable(View v){


    }

    //删除数据表
    public void dropTable(View v){

    }
}

3. 建立一个员工实体类

public class Emp {
    //id号
    private int id;
    //员工姓名
    private String name;

    //员工年龄
    private int age;

    public Emp() {}

    public Emp(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = 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;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

员工实体类讲解

  1. 我这里主要包含三个属性(可以自由发挥)
    1. 员工编号
    2. 员工姓名
    3. 员工年龄
  2. 实体类可以自己定义,只要符合业务需求即可

4. MySQLiteOpenHelper(名字有点Low~ haha~)


  1. 代码

public class MyDatabaseHelper extends SQLiteOpenHelper {
    //定义数据表
    public static final String TAB_NAME ="emp.db";

    //定义列
    public static final String NAME = "name";
    public static final String AGE = "age";

    //定义建表语句
    public static final String CREATE_EMP="CREATE TABLE emp(" +
                                            "id PRIMARY KEY AUTOINCREMENT," +
                                            "name VARCHAR(20) NOT NULL," +
                                            "age INT)";
    //定义数据库版本
    public static final int version = 1;
    

    public MyDatabaseHelper(Context context) {
        super(context, TAB_NAME, null, version, null);
    }

    //当没有表的时候执行此方法
    @Override
    public void onCreate(SQLiteDatabase db) {
        //写入建表语句
        db.execSQL(CREATE_EMP);
    }

    //当数据库版本不对的时候调用此方法。
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

SQLiteOpenHelper 管理数据库创建和版本管理的辅助类.。

  1. SQLiteOpenHelper 是一个抽象类,想要使用它的话,就需要创建一个自己的帮助类去继承它。并复写两个抽象方法
    1.1 onCreate():创建时执行,已经存在不执行。
1.2 **onUpgrade()**:版本号不同时执行
  1. 两个重要的实例方法
    2.1 **getReadableDatabase() **
  2.2 **getWritableDatabase()**。
*  这两个方法都可以**创建或打开**一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库)。
* 并返回一个可对数据库进行读写操作的对象。
* 不同处。当数据库不可写入时(如磁盘空间已满)getReadableDatabase() 方法返回的对象将以只读的方式去打开数据库,而 getWritableDatabase() 方法则将出现异常。
  1. 创建数据库的步骤
    构建出** SQLiteOpenHelper 实例
    再调用它的 getReadableDatabase()
    getWritableDatabase() **方法就能够创建数据库了。
    数据库文件会存放在 **/data/data/<package name>/databases/ 目录下。
    此时,重写的
    onCreate() **方法也会得到执行
  1. 官方文档:SQLiteOpenHelper

5.定义数据适配器

1.代码:



public class DatabaseAdapter {
  //持有一个帮助类
  MyDatabaseHelper helper;

  public DatabaseAdapter(Context context) {
      helper = new MyDatabaseHelper(context);
  }

  //具体的添加操作
  public void insert(Emp emp){
      //获取写数据库的权限
      SQLiteDatabase db =helper.getWritableDatabase();

      ContentValues values = new ContentValues();
      values.put(MyDatabaseHelper.NAME,emp.getName());
      values.put(MyDatabaseHelper.AGE,emp.getAge());
      //插入操作
      db.insert(MyDatabaseHelper.TAB_NAME,null,values);
  }

  //具体的修改操作
  public void update(Emp emp){
      //获取写数据的权限
      SQLiteDatabase db = helper.getWritableDatabase();
      //修改的条件
      String whereClause = "id=?";

      //修改的条件参数
      String[] whereArgs = new String[]{"1"};

      //修改的内容
      ContentValues values = new ContentValues();
      values.put(MyDatabaseHelper.ID,emp.getId());
      values.put(MyDatabaseHelper.NAME,emp.getName());
      values.put(MyDatabaseHelper.AGE,emp.getAge());

      //修改操作
      db.update(MyDatabaseHelper.TAB_NAME,values,whereClause,whereArgs);
  }

  //具体的删除操作
  public void delete(int id){
      //获取写数据的权限
      SQLiteDatabase db = helper.getWritableDatabase();
      String whereClause = "id=?";
      String[] whereArgs = new String[]{String.valueOf(id)};
      db.delete(MyDatabaseHelper.TAB_NAME,whereClause,whereArgs);
  }

  //具体的查询单个操作
  public Emp find(int id){
      //创建实体类对象
      Emp emp = null;
      //获取查询数据的权限
      SQLiteDatabase db = helper.getReadableDatabase();
      String[] columns = new String[]{MyDatabaseHelper.ID,MyDatabaseHelper.NAME,MyDatabaseHelper.AGE};
      String selection = "id=?";
      String[] selectionArgs = new String[]{String.valueOf(id)};
      Cursor result = db.query(MyDatabaseHelper.TAB_NAME,columns,selection,selectionArgs,null,null,null);
      //循环取值
      if (result.moveToFirst()){
          emp = new Emp();
          emp.setId(result.getInt(0));
          emp.setName(result.getString(1));
          emp.setAge(result.getInt(2));
      }
      result.close();
      return emp;
  }

  //具体的查询所有操作
  public List<Emp> findAll(){
      //创建list集合
      List<Emp> list = new ArrayList<>();
      //获取读取数据库的权限
      SQLiteDatabase db = helper.getReadableDatabase();
      String[] columns = new String[]{MyDatabaseHelper.ID,MyDatabaseHelper.NAME,MyDatabaseHelper.AGE};
      Cursor res = db.query(MyDatabaseHelper.TAB_NAME,columns,"",new String[]{},null,null,null);
      while (res.moveToNext()){
          Emp emp = new Emp();
          emp.setId(res.getInt(0));
          emp.setName(res.getString(1));
          emp.setAge(res.getInt(2));
          list.add(emp);
      }
      res.close();
      return list;
  }

  //具体的删表操作
  public void dropTable(){
      //获取写数据的权限
      SQLiteDatabase db = helper.getWritableDatabase();
      db.execSQL(MyDatabaseHelper.DROP_EMP);
  }

  //具体的建表操作
  public void createTable(){
      //获取写数据的权限
      SQLiteDatabase db = helper.getWritableDatabase();
      db.execSQL(MyDatabaseHelper.CREATE_EMP);
  }
}

讲解
此适配器主要是帮我们具体的实现具体的业务操作而写的,我这里只是练习,未来你需要根据具体的业务去实现

最后完成这样的效果

效果图

开始写内容提供者


  /**
 * 内容提供者练习
 */
public class MyContentProvider extends ContentProvider {

    //定义一个URI匹配器
    public static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    //定义常量
    public static final int INSERT = 1;
    public static final int DELETE = 2;
    public static final int UPDATE = 3;
    public static final int QUERYBYID = 4;
    public static final int QUERY = 5;

    //持有引用
    MyDatabaseHelper helper;


    static {
        //匹配的内容: content://cn.jewei.provider.emp/insert
        matcher.addURI("cn.jewei.provider.emp","insert",INSERT);
        //匹配的内容: content://cn.jewei.provider.emp/delete
        matcher.addURI("cn.jewei.provider.emp","delete",DELETE);
        //匹配的内容: content://cn.jewei.provider.emp/update
        matcher.addURI("cn.jewei.provider.emp","update",UPDATE);
        //匹配的内容: content://cn.jewei.provider.emp/query/5后面是数字的这种
        matcher.addURI("cn.jewei.provider.emp","query/#",QUERYBYID);
        //匹配的内容: content://cn.jewei.provider.emp/query
        matcher.addURI("cn.jewei.provider.emp","query",QUERY);
    }

    public MyContentProvider() {
    }

    //启动的时候就会执行
    @Override
    public boolean onCreate() {
        //初始化帮助类
        helper = new MyDatabaseHelper(getContext());
        return true;
    }

    //增加数据的操作
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //首先匹配URI
        if (matcher.match(uri) == INSERT){//匹配上就返回INSERT的值
            SQLiteDatabase db = helper.getWritableDatabase();
            //执行插入操作
            db.insertOrThrow(MyDatabaseHelper.TAB_NAME,null,values);
        }
        return uri;
    }
    //删除操作
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if (matcher.match(uri) == DELETE){
            SQLiteDatabase db = helper.getWritableDatabase();
            db.delete(MyDatabaseHelper.TAB_NAME,selection,selectionArgs);

        }
        return 0;
    }
    //更新操作
    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        if (matcher.match(uri) == UPDATE){
            SQLiteDatabase db = helper.getWritableDatabase();
            db.update(MyDatabaseHelper.TAB_NAME,values,selection,selectionArgs);
        }
        return 0;
    }

    //查询操作
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        if (matcher.match(uri) == QUERYBYID){//查询单个操作
            long id = ContentUris.parseId(uri);
            SQLiteDatabase db = helper.getReadableDatabase();
            return db.query(MyDatabaseHelper.TAB_NAME,projection,"id=?",new String[]{id+""},null,null,null);

        }else if(matcher.match(uri) == QUERY){//查询所有
            SQLiteDatabase db = helper.getReadableDatabase();
            return db.query(MyDatabaseHelper.TAB_NAME,projection,null,null,null,null,null);
        }
        return null;
    }
    //主要用于查询是返回单个还是多个
    @Override
    public String getType(Uri uri) {
        if (matcher.match(uri) == QUERYBYID){//查询单个操作
            Log.i("privder","查询单个");
            return "vnd.android.cursor.item/emp";
        }else if(matcher.match(uri) == QUERY){//查询所有
            Log.i("privder","查询一组");
            return "vnd.android.cursor.dir/";
        }
        return "";
    }
}

知识点:

  • Uri(统一资源表示符)
    适合不监测网络连接的通信机制
URI图例
  • 建立内容提供者的目的是提供一种安全的访问形式,就如同防火墙一样,允许可以访问的内容,拒绝一切非法的访问,我们学习内容提供者的目的试了以后能更好的使用系统提供给我们的信息,如果未来你做的应用特别大的时候,里面得数据足够提供一种服务的时候,这个时候内容提供者对你就特别的重要了。

编写另一个应用,模拟查询上一个应用的数据,完成内容提供者的整个流程

  1. 废话不多说,布局和上面的一样,这里不再写出
    1.1 一张截图:
接收的界面
  1. 我们开始写Activity的内容接收具体代码
public class MainActivity extends AppCompatActivity {

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

    //增加数据
    public void insert(View v){
        //创建一个内容接收者
        ContentResolver resolver = getContentResolver();
        ContentValues values = new ContentValues();
        values.put("name","张无忌");
        values.put("age",18);
        Uri uri = Uri.parse("content://cn.jewei.provider.emp/insert");
        resolver.insert(uri,values);
    }

    //修改数据
    public void update(View v){
        //创建一个内容接收者
        ContentResolver resolver = getContentResolver();
        //创建一个ContentValues用于存储数据
        ContentValues values = new ContentValues();
        values.put("id",1);
        values.put("name","谢逊");
        values.put("age",84);
        Uri uri = Uri.parse("content://cn.jewei.provider.emp/update");
        resolver.update(uri,values,"id=?",new String[]{"1"});
    }

    //删除数据
    public void delete(View v){
        //创建一个内容接收者
        ContentResolver resolver = getContentResolver();
        //创建uri
        Uri uri = Uri.parse("content://cn.jewei.provider.emp/delete");
        resolver.delete(uri,"id=?",new String[]{"1"});
    }

    //查询单个数据
    public void find(View v){
        //创建一个内容接收者
        ContentResolver resolver = getContentResolver();
        //创建uri
        Uri uri = Uri.parse("content://cn.jewei.provider.emp/query/2");

        //定义列
        String[] column = new String[]{"id","name","age"};
        Cursor res = resolver.query(uri,column,"id=?",new String[]{"2"},null);
        Emp emp =null;
        if (res.moveToNext()){
            emp = new Emp();
            emp.setId(res.getInt(0));
            emp.setName(res.getString(1));
            emp.setAge(res.getInt(2));
        }

        Toast.makeText(this,emp.toString(), Toast.LENGTH_SHORT).show();


    }

    //查询所有
    public void findAll(View v){
        //装在的容器
        List<Emp> list=new ArrayList<>();

        //创建一个内容接收者
        ContentResolver resolver = getContentResolver();
        //创建uri
        Uri uri = Uri.parse("content://cn.jewei.provider.emp/query");

        //定义列
        String[] column = new String[]{"id","name","age"};
        Cursor res = resolver.query(uri,column,null,null,null);
        Emp emp =null;
        while (res.moveToNext()){
            emp = new Emp();
            emp.setId(res.getInt(0));
            emp.setName(res.getString(1));
            emp.setAge(res.getInt(2));
            list.add(emp);
        }
        Toast.makeText(this, Arrays.toString(list.toArray()), Toast.LENGTH_SHORT).show();
    }}

效果图

运行效果图

总结:
掌握好内容提供者的编写,能够更加的了解内部的机制,有助于我们更好地调用其他应用的数据,我这里没有设定任何的权限,正常来讲,我们可以自定义权限的,这时候调用者访问我们的应用中的数据就必须携带权限才可以,和系统的权限一样,没有权限你看不到,哈哈哈~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容