Android---------------ContentProvider的学习

时间:2024-08-01 10:33:20

Android---------------ContentProvider的学习

1.Uri  uri = Intent.getData()------------->可以获得Uri的地址

2.Cursor cursor = getContentResolver().query(uri , null , null , null ,null);  ------------->这句话相当得到空行那个位置

3.cursor.moveToFirst()------------------------------>定位到第一行

4.String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))

getColumnIndex(String columnName)  :  返回指定列的名称,如果不存在返回-1

总结:跨进程访问和进程间内部访问区别在于Mainfest.xml文件中的权限的问题

注意事项 : 一定在Mainfest里面注册信息

<provider android:name="MyProvider"
android:authorities="cn.scu.myprovider"/>

进程内访问的一般步骤:

  1. 创建数据库类
  2. 自定义 ContentProvider
  3. 注册 创建的 ContentProvider类--------->指的是.xml文件里面的东西
  4. 进程内访问 ContentProvider的数据

UriMatcher类的作用

  • ContentProvider 中注册URI
  • 根据 URI 匹配 ContentProvider 中对应的数据表

在CotentProvider的这个类中写的

public static final String AUTOHORITY = "cn.scu.myprovider";
// 设置ContentProvider的唯一标识 public static final int User_Code = 1;
public static final int Job_Code = 2; // UriMatcher类使用:在ContentProvider 中注册URI
private static final UriMatcher mMatcher;
static{
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 初始化
mMatcher.addURI(AUTOHORITY,"user", User_Code);
mMatcher.addURI(AUTOHORITY, "job", Job_Code);
// 若URI资源路径 = content://cn.scu.myprovider/user ,则返回注册码User_Code
// 若URI资源路径 = content://cn.scu.myprovider/job ,则返回注册码Job_Code
}
/**
* 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
*/
private String getTableName(Uri uri){
String tableName = null;
switch (mMatcher.match(uri)) {
case User_Code:
tableName = user //这个返回代表是表名
break;
case Job_Code:
tableName = job;
break;
}
return tableName;
}
    @Override
public Uri insert(Uri uri, ContentValues values) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
// 该方法在最下面
String table = getTableName(uri);
// 向该表添加数据
db.insert(table, null, values);
// 当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
mContext.getContentResolver().notifyChange(uri, null);
// // 通过ContentUris类从URL中获取ID
// long personid = ContentUris.parseId(uri);
// System.out.println(personid);
return uri;
}
    /**
* 查询数据
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
// 该方法在最下面
String table = getTableName(uri); // // 通过ContentUris类从URL中获取ID
// long personid = ContentUris.parseId(uri);
// System.out.println(personid);
// 查询数据
return db.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
MatrixCursor matrixCursor;
switch (sUriMatcher.match(uri)) {
case LUCKY_MONEY_ENABLE:
matrixCursor = new MatrixCursor(new String[]{
TABLE_COLUMN
});
matrixCursor.addRow(new Object[]{
mCommonConfig.getXiaomiLuckyMoneyEnable() ? true : false
});
break;
case LUCKY_MONEY_FAST_OPEN:
matrixCursor = new MatrixCursor(new String[]{
TABLE_COLUMN
});
matrixCursor.addRow(new Object[]{
mCommonConfig.isFastOpenEnable() ? true : false
});
break;
case LUCKY_MONEY_FLOAT:
matrixCursor = new MatrixCursor(new String[]{
TABLE_COLUMN
});
matrixCursor.addRow(new Object[]{
mCommonConfig.isDesktopFloatWindowEnable() ? true : false
});
break;
case LUCKY_NETWORK_LATENCY:
matrixCursor = new MatrixCursor(new String[]{
TABLE_COLUMN
});
matrixCursor.addRow(new Object[]{
mCommonConfig.getNetworkReduceLatency() ? true : false
});
break;
case LUCKY_MONEY_HB_INFO:
matrixCursor = new MatrixCursor(new String[]{
"num_total",
"money_total",
"mm_money_total",
"qq_money_total",
"max_person",
"max_group"
});
matrixCursor.addRow(new Object[]{
mCommonConfig.getWarningLuckyMoneyCount(),
mCommonConfig.getReceiveTotalLuckyMoney(),
mCommonConfig.getMMMoney(),
mCommonConfig.getQQMoney(),
mCommonConfig.getPersonalLuckyMaxSource(),
mCommonConfig.getLuckyMaxSource()
});
break;
default:
return null;
}
return matrixCursor;
}

在MainActivity中写的
Uri uri_job = Uri.parse("content://cn.scu.myprovider/job");
// 插入表中数据
ContentValues values2 = new ContentValues();
values2.put("_id", 3);
values2.put("job", "NBA Player"); // 获取ContentResolver
ContentResolver resolver2 = getContentResolver();
// 通过ContentResolver 根据URI 向ContentProvider中插入数据
resolver2.insert(uri_job, values2); // 通过ContentResolver 向ContentProvider中查询数据
Cursor cursor2 = resolver2.query(uri_job, new String[]{"_id", "job"}, null, null, null);
while (cursor2.moveToNext()) {
//System.out.println("query job:" + cursor2.getInt(0) + " " + cursor2.getString(1));
// 将表中数据全部输出
Log.i("ceshi", "int ===" + cursor2.getInt(0));
Log.i("ceshi", "String ===" + cursor2.getString(1));
}
cursor2.close();
// 关闭游标
} Url url = Url.parse("content://cn.scu.myprovider/job");
ContentValues value = new ContentValues();
value.put(-_id , 3);
vlaue.put(name , "lisan");
ContentResolver resolver = getContentResolver();
resolver.insert(url,value); --------------------------------->它实际调用的是ContentProvider里面写的那个insert()函数 Cursor cursor = resolver.query(url , null , null ,null , null);------>它实际调用的是ContentProvider里面写的那个query那个函数
while(cursor.moveToNext){ }
cursor.close() -------->一定关闭游标卡尺 ContentObserver类
  
  定义:内容观察者
    作用:观察 Uri引起 ContentProvider 中的数据变化 & 通知外界(即访问该数据访问者)
    当ContentProvider 中的数据发生变化(增、删 & 改)时,就会触发该 ContentObserver类
    具体使用
// 步骤1:注册内容观察者ContentObserver
    getContentResolver().registerContentObserver(uri);-------->注册监听器
    // 通过ContentResolver类进行注册,并指定需要观察的URI // 步骤2:当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
    public class UserContentProvider extends ContentProvider {
      public Uri insert(Uri uri, ContentValues values) {
      db.insert("user", "userid", values);
      getContext().getContentResolver().notifyChange(uri, null);
      // 通知访问者
   }
} // 步骤3:解除观察者
 getContentResolver().unregisterContentObserver(uri);
    // 同样需要通过ContentResolver类进行解除 //注册ContentProvider的观察者
this.getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsObserver(new Handler()));
//根据自定义的ContentObserver监听类
    private final class SmsObserver extends ContentObserver
    {
        public SmsObserver(Handler handler) {
            super(handler);
        }         public void onChange(boolean selfChange)
        {
    //这里面就是接受notifyChange的改变做相应的处理
    getContext().getContentResolver().notifyChange(uri, null);
        }
    }

进程间进行数据共享

  1. 创建数据库类
  2. 自定义 ContentProvider
  3. 注册 创建的 ContentProvider

进程1的AndroidManifest.xml的文件

  <provider android:name="MyProvider"

  android:authorities="scut.carson_ho.myprovider"

  // 声明外界进程可访问该Provider的权限(读 & 写)

  android:permission="scut.carson_ho.PROVIDER"

  // 权限可细分为读 & 写的权限

  // 外界需要声明同样的读 & 写的权限才可进行相应操作,否则会报错

   //android:readPermisson = "scut.carson_ho.Read"

   // android:writePermisson = "scut.carson_ho.Write"

  // 设置此provider是否可以被其他进程使用

  android:exported="true" />

进程2的AndroidManifest.xml的文件

// 声明本应用可允许通信的权限(全权限)

<uses-permission android:name="scut.carson_ho.PROVIDER"/>

// 细分读 & 写权限如下,但本Demo直接采用全权限

//<uses-permission android:name="scut.carson_ho.Read"/>

///  <uses-permission android:name="scut.carson_ho.Write"/>

// 注:声明的权限必须与进程1中设置的权限对应