首页   

四大应用组件ContentProvider

小置同学  ·  · 4 年前

1. 认识
ContentProvider用于应用B数据库暴露接口, A应用通过ContentResolver访问B接口,读取数据库数据
Uri格式:
content: //  com.example.transupportprovider/trains/122
前缀 :   //  唯一标识                       / 表  / 表id
ContentProvider的前缀就是:content
唯一标识 :  用包名一般
2. 通过ContentResolver  实现 A应用  对 B应用 ContentResolver 暴露接口的访问

A应用暴露接口
2.1  DBHelper.java   提供内部数据库访问

package com.example.myapplication;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * 数据库操作的帮助类
 * @author denganzhi
 *
 */
public class DBHelper extends SQLiteOpenHelper {


	public DBHelper(Context context,int version) {
		super(context, "atguigu.db", null, version);
	}

	/**
	 * 什么时候才会创建数据库文件?
	 * 	1). 数据库文件不存在
	 *  2). 连接数据库
	 * 
	 * 什么时候调用?
	 * 	当数据库文件创建时调用(1次)
	 * 在此方法中做什么?
	 * 	建表
	 * 	插入一些初始化数据
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.e("TAG", "DBHelper onCreate()");
		//建表
		String sql = "create table person(_id integer primary key autoincrement, name varchar,age int)";
		db.execSQL(sql);
		//插入一些初始化数据
		db.execSQL("insert into person (name, age) values ('Tom1', 11)");
		db.execSQL("insert into person (name, age) values ('Tom2', 12)");
		db.execSQL("insert into person (name, age) values ('Tom3', 13)");
	}

	//当传入的版本号大于数据库的版本号时调用
	// 用户版本升级
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.e("TAG", "DBHelper onUpgrade()-->"+"oldVersion:"+oldVersion + "newVersion:"+newVersion);
	}
    // 还有版本下降的时候调用的方法onDowngrade
}

2.2 PersonProvider.java:  实现ContentProvider  接口暴露方法

package com.example.myapplication;

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

/**
 * 操作person表的provider类
 *
 */
public class PersonProvider extends ContentProvider {

	//用来存放所有合法的Uri的容器,这里的参数是如果url不能匹配返回的值:-1一般返回
	private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
	//保存一些合法的uri
	// 前缀:// provider的唯一标识/表明/id
	// content://com.atguigu.l09_provider.personprovider/person 不根据id操作
	// content://com.atguigu.l09_provider.personprovider/person/3 根据id操作
	static {
		matcher.addURI("com.example.myapplication.PersonProvider", "/person", 1);
		matcher.addURI("com.example.myapplication.PersonProvider", "/person/#", 2);  //#匹配任意数字
	}
	private DBHelper dbHelper;
	public PersonProvider() {
		Log.e("TAG", "PersonProvider()");
	}
	// 当内容提供者被创建的时候调用,适合做数据初始化操作
	@Override
	public boolean onCreate() {
		Log.e("TAG", "PersonProvider onCreate()");
		dbHelper = new DBHelper(getContext(),1);

		return false;
	}

	/**
	 * content://com.atguigu.l09_provider.personprovider/person 不根据id查询
	 * content://com.atguigu.l09_provider.personprovider/person/3 根据id查询
	 * 查询表数据:
	 *  URI:地址
	 *  projection: 查询那些字段
	 *  String selection,
	 String[] selectionArgs 查询条件,条件中可能有?

	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
						String[] selectionArgs, String sortOrder) {
		Log.e("TAG", "PersonProvider query()");

		//得到连接对象
		SQLiteDatabase database = dbHelper.getReadableDatabase();

		//1.匹配uri, 返回code
		int code = matcher.match(uri);
		//如果合法, 进行查询
		if(code==1) {//不根据id查询,配合1
			Cursor cursor = database.query("person", projection, selection, selectionArgs, null, null, null);
			return cursor;
		} else if(code==2) {//根据id查询,匹配2
			//得到id
			long id = ContentUris.parseId(uri);
			//查询
			Cursor cursor = database.query("person", projection, "_id=?", new String[]{id+""}, null, null, null);
			return cursor;
		} else {//如果不合法, 抛出异常
			throw new RuntimeException("查询的uri不合法");
		}
	}

	/**
	 * content://com.atguigu.l09_provider.personprovider/person 插入
	 * content://com.atguigu.l09_provider.personprovider/person/3 根据id插入(没有)
	 * values: map接口插入数据
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		Log.e("TAG", "PersonProvider insert()");
		//得到连接对象
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//匹配uri, 返回code
		int code = matcher.match(uri);
		//如果合法, 进行插入
		if(code==1) {
			long id = database.insert("person", null, values);
			//将id添加到uri中
			uri = ContentUris.withAppendedId(uri, id);
			database.close();
			return uri;
		} else {
			//如果不合法, 抛出异常
			database.close();
			throw new RuntimeException("插入的uri不合法");
		}
	}

	/**
	 * content://com.atguigu.l09_provider.personprovider/person 不根据id删除
	 * content://com.atguigu.l09_provider.personprovider/person/3 根据id删除
	 *
	 * String selection, String[] selectionArgs: 删除条件
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		Log.e("TAG", "PersonProvider delete()");
		//得到连接对象
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//匹配uri, 返回code
		int code = matcher.match(uri);
		int deleteCount = -1;
		//如果合法, 进行删除
		if(code==1) {
			deleteCount = database.delete("person", selection, selectionArgs);
		} else if(code==2) {
			long id = ContentUris.parseId(uri);
			deleteCount = database.delete("person", "_id="+id, null);
		} else {
			//如果不合法, 抛出异常
			database.close();
			throw new RuntimeException("删除的uri不合法");
		}

		database.close();
		return deleteCount;
	}

	/**
	 * content://com.atguigu.l09_provider.personprovider/person 不根据id更新
	 * content://com.atguigu.l09_provider.personprovider/person/3 根据id更新
	 *
	 * values: map更新数据
	 *  String selection,
	 String[] selectionArgs 更新条件
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
					  String[] selectionArgs) {
		Log.e("TAG", "PersonProvider update()");
		//得到连接对象
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//匹配uri, 返回code
		int code = matcher.match(uri);
		int updateCount = -1;
		//如果合法, 进行更新
		if(code==1) {
			updateCount = database.update("person", values, selection, selectionArgs);
		} else if(code==2) {
			long id = ContentUris.parseId(uri);
			updateCount = database.update("person", values, "_id="+id, null);
		} else {
			//如果不合法, 抛出异常
			database.close();
			throw new RuntimeException("更新的uri不合法");
		}

		database.close();
		return updateCount;
	}
	// MIME:
	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		return null;
	}
}

B应用使用 ContentResolver 访问暴露接口,协议 Uri 的格式

通过ContentResolver 接口,访问ContentProvider  暴露的方法


    public static String prividerStr="content://com.example.myapplication.PersonProvider/person";
    /*
	 * 通过ContentResolver调用ContentProvider查询所有记录
	 */
    public void selectProvier(View v) {
        //1. 得到ContentResolver对象
        ContentResolver resolver = getContentResolver();
        //2. 调用其query, 得到cursor
        Uri uri = Uri.parse("content://com.example.myapplication.personprovider/person/1");
        uri = Uri.parse(prividerStr);
        Cursor cusor = resolver.query(uri, null, null, null, null);
        //3. 取出cursor中的数据, 并显示
        if(cusor!=null){
            while(cusor.moveToNext()) {
                int id = cusor.getInt(0);
                String name = cusor.getString(1);
                Toast.makeText(this, id+" : "+name, 1).show();
            }
            cusor.close();
        }

    }

    public void addFun(View view) {

        //1. 得到ContentResolver对象
        ContentResolver resolver = getContentResolver();
        //2. 调用其insert
        Uri uri = Uri.parse(prividerStr);
        //uri = Uri.parse("content://com.atguigu.l09_provider.personprovider/person/3");
        ContentValues values = new ContentValues();
        values.put("name", "JACK");
        uri = resolver.insert(uri, values);

        Toast.makeText(this, uri.toString(), 1).show();
    }

    public void updateFun(View view) {
        //1. 得到ContentResolver对象
        ContentResolver resolver = getContentResolver();
        //2. 执行update
        Uri uri = Uri.parse("content://com.example.myapplication.PersonProvider/person/10");
        ContentValues values = new ContentValues();
        values.put("name", "JACK2");
        // 返回更新成功个数
        int updateCount = resolver.update(uri, values, null, null);

        Toast.makeText(this, "updateCount="+updateCount, 1).show();
    }

    public void deleteFun(View view) {
        //1. 得到ContentResolver对象
        ContentResolver resolver = getContentResolver();
        //2. 执行delete
        Uri uri = Uri.parse("content://com.example.myapplication.PersonProvider/person/2");
        int deleteCount = resolver.delete(uri, null, null);
        Toast.makeText(this, "deleteCount="+deleteCount, 1).show();
    }

案例, 访问联系人:AndroidManifest.xml

  <!-- 读取联系人记录的权限 -->
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

Java 代码:系统已经提供了现成的CONTENT_URI ,把数据库字段封装成了常量

  private static final int MY_PERMISSIONS_REQUEST_CALL_PHONE =10 ; 
public void selectContacts(View view) {

        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED)
        {

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_CALL_PHONE);
        } else
        {
            selectContacts();
        }
    }

    public void selectContacts() {
        ContentResolver resolver = getContentResolver();
        //执行查询得到cursor
        String[] projection = {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
        Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null);
        //取出其中的数据保存到data
        while(cursor.moveToNext()) {
            String name = cursor.getString(0);
            String number = cursor.getString(1);
            Map<String, String> map = new HashMap<String, String>();
            map.put("name", name);
            map.put("number", number);
            Log.e("denganzhi","name:"+name   + "number:"+ number);
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
    {

        if (requestCode == MY_PERMISSIONS_REQUEST_CALL_PHONE)
        {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                selectContacts();
            } else
            {
                // Permission Denied
                Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

源码路径: https://download.csdn.net/download/dreams_deng/12233364

推荐文章
闹闹每日星运  ·  春天来了,再不谈恋爱就亏大了  ·  1 月前  
北京大学金融法研究中心  ·  变幻的 “货币” 与虚幻的 “货币宪法” — ...  ·  3 年前  
一罐 app(微博搜索)  ·  一罐 app(微博搜索)-20181219-1  ·  5 年前  
© 2022 51好读
删除内容请联系邮箱 2879853325@qq.com