最近利用下班时间,找了看什么书比较适合初学android的朋友,很多人推荐了这本书,于是就买了一本,感觉看书,思考,动手,再思考和总结这样过程还是很有必要的,于是就打算把自己学习的东西简单的总结一下;方便自己以后查找,也有利于学习的巩固。在这里首先要感谢一下书籍的作者——郭霖前辈。
上一部分我们介绍了一些基础知识以及如何访问别的程序的中数据,并给出了访问系统联系人应用中的联系人数据,今天我们就来看看其他应用究竟是怎么通过内容提供者把自己的数据提供出来的。关于这部分的内容,如果是对SQLite比较陌生的朋友,可以提前熟悉一下SQLite的基本使用。好的,在这些条件都具备的时候,我们就可以开始具体的内容了。
1,通过内容提供者提供数据访问接口实现步骤
-
自定义内容提供者
-
构建外部访问的Uri,并添加到UriMatcher里面
-
重写内部六个方法,分别是CURD四个方法以及onCreate()和getType(),利用外部访问Uri与自定义代码建立联系
这样三步,就完成了我们的目标。
(1)自定义内容提供者
我们实现主要有两种方式:
- 自定义类继承android.content.ContentProvider,需要手动添加配置文件
- 通过AS快捷键或者new的方式,不需要手动添加配置文件
(2)构建外部访问的Uri,并添加到UriMatcher里面
这个操作的目的主要是我们之前说的,控制外部可访问的数据,保护自身的隐私数据,也就是说只有在UriMatcher里面添加的Uri子项的数据外部才可以访问,例如如下代码:
static {
matcher = new UriMatcher(UriMatcher.NO_MATCH);
//添加对外内容URI,通常是包名+表名/或者通配符+通配符
matcher.addURI(authority, "student", TAB_STUDENT);
matcher.addURI(authority, "student/#", COW_STUDENT);
matcher.addURI(authority, "teacher", TAB_TEACHER);
matcher.addURI(authority, "teacher/#", COW_TEACHER);
}
(3)重写ContentProvider中的六个方法,实现外部对可访问数据的操作,例如insert():
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
SQLiteDatabase sqLiteDatabase = sqLiterHelper.getReadableDatabase();
Uri uriReturn=null;
switch (matcher.match(uri)) {
case TAB_STUDENT:
long newStudentId =sqLiteDatabase.insert("student",null,values);
uriReturn=Uri.parse("content://"+authority+"/student/"+newStudentId);
break;
case COW_STUDENT:
break;
case TAB_TEACHER:
long newTeacherId =sqLiteDatabase.insert("teacher",null,values);
uriReturn=Uri.parse("content://"+authority+"/teacher/"+newTeacherId);
break;
case COW_TEACHER:
break;
default:
break;
}
return uriReturn;
}
2,示例
这一部分,为了效果,创建了两个应用,分别是OperationContentProviderB(提供数据)和OperationContentProviderA(访问数据),下面就来看看具体的代码和实现效果:
OperationContentProviderB(提供数据)中
MainActivity.java代码:
package com.hfut.operationcontentproviderb;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.content.ContentValues;
import android.widget.TextView;
/**
* @author why
* @date 2018-11-6 18:47:07
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private MySQLiterHelper mySQLiteHelperBase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void createStudentTab(View view) {
mySQLiteHelperBase = new MySQLiterHelper(this, "school", null, 1);
SQLiteDatabase sqLiteDatabase = mySQLiteHelperBase.getReadableDatabase();//创建数据库
initDataStudent(sqLiteDatabase);//初始化数据库数据
}
public void createTeacherTab(View view) {
mySQLiteHelperBase = new MySQLiterHelper(this, "school", null, 1);
SQLiteDatabase sqLiteDatabase = mySQLiteHelperBase.getReadableDatabase();//创建数据库
initDataTeacher(sqLiteDatabase);//初始化数据库数据
}
/**
* 初始化数据库student数据
*/
private void initDataStudent(SQLiteDatabase sqLiteDatabase) {
ContentValues contentValues = new ContentValues();
contentValues.put("name", "why");
contentValues.put("age", 26);
contentValues.put("sex", "male");
sqLiteDatabase.insert("student", null, contentValues);
contentValues.clear();
contentValues.put("name", "jr");
contentValues.put("age", 24);
contentValues.put("sex", "female");
sqLiteDatabase.insert("student", null, contentValues);
contentValues.clear();
contentValues.put("name", "xiaoming");
contentValues.put("age", 34);
contentValues.put("sex", "unkown");
sqLiteDatabase.insert("student", null, contentValues);
contentValues.clear();
Log.d(TAG, "initData: 执行了数据添加操作");
Cursor cursor = sqLiteDatabase.query("student", null, null, null, null, null, null);
StringBuilder builder = new StringBuilder();
builder.append(" student表数据:\n");
while (cursor.moveToNext()) {
builder.append("name: " + cursor.getString(cursor.getColumnIndex("name")) +
" age: " + cursor.getInt(cursor.getColumnIndex("age")) +
" sex: " + cursor.getString(cursor.getColumnIndex("sex")) + "\n");
}
((TextView) findViewById(R.id.dbData)).setText(builder.toString());
}
/**
* 初始化数据库teacher数据
*/
private void initDataTeacher(SQLiteDatabase sqLiteDatabase) {
ContentValues contentValues = new ContentValues();
contentValues.put("name", "why");
contentValues.put("teacherID", 1);
contentValues.put("subject", "computer");
sqLiteDatabase.insert("teacher", null, contentValues);
contentValues.clear();
contentValues.put("name", "jr");
contentValues.put("teacherID", 2);
contentValues.put("subject", "math");
sqLiteDatabase.insert("teacher", null, contentValues);
contentValues.clear();
contentValues.put("name", "xiaoming");
contentValues.put("teacherID", 3);
contentValues.put("subject", "biology");
sqLiteDatabase.insert("teacher", null, contentValues);
contentValues.clear();
Log.d(TAG, "initData: 执行了数据添加操作");
Cursor cursor = sqLiteDatabase.query("teacher", null, null, null, null, null, null);
StringBuilder builder = new StringBuilder();
builder.append(" teacher表数据\n");
while (cursor.moveToNext()) {
builder.append("name: " + cursor.getString(cursor.getColumnIndex("name")) +
" teacherID: " + cursor.getInt(cursor.getColumnIndex("teacherID")) +
" subject: " + cursor.getString(cursor.getColumnIndex("subject")) + "\n");
}
((TextView) findViewById(R.id.dbData)).setText(builder.toString());
}
}
MyProvider.java代码:
package com.hfut.operationcontentproviderb;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
* author:why
* created on: 2018/11/6 18:51
* description:
*/
public class MyProvider extends ContentProvider {
public static final int TAB_STUDENT = 1;
public static final int COW_STUDENT = 2;
public static final int TAB_TEACHER = 3;
public static final int COW_TEACHER = 4;
private static UriMatcher matcher;
private MySQLiterHelper sqLiterHelper;
private static String authority = "com.hfut.operationcontentproviderb";
private String dirType = "vnd.android.cursor.dir/";
private String itemType = "vnd.android.cursor.item/";
static {
matcher = new UriMatcher(UriMatcher.NO_MATCH);
//添加对外内容URI,通常是包名+表名/或者通配符+通配符
matcher.addURI(authority, "student", TAB_STUDENT);
matcher.addURI(authority, "student/#", COW_STUDENT);
matcher.addURI(authority, "teacher", TAB_TEACHER);
matcher.addURI(authority, "teacher/#", COW_TEACHER);
}
@Override
public boolean onCreate() {
sqLiterHelper = new MySQLiterHelper(getContext(), "school", null, 1);
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder) {
SQLiteDatabase sqLiteDatabase = sqLiterHelper.getReadableDatabase();
Cursor cursor = null;
switch (matcher.match(uri)) {
case TAB_STUDENT://查询student全表
cursor = sqLiteDatabase.query("student", projection, selection, selectionArgs,
null, null, sortOrder);
break;
case COW_STUDENT://查询student表中i指定id的行
String studentId = uri.getPathSegments().get(1);
cursor = sqLiteDatabase.query("student", projection, "id=?",
new String[]{studentId}, null, null, sortOrder);
break;
case TAB_TEACHER:
cursor = sqLiteDatabase.query("teacher", projection, selection, selectionArgs,
null, null, sortOrder);
break;
case COW_TEACHER:
String teacherId = uri.getPathSegments().get(1);
cursor = sqLiteDatabase.query("teacher", projection, "id=?",
new String[]{teacherId}, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
String str = "";
switch (matcher.match(uri)) {
case TAB_STUDENT:
str = dirType + "vnd." + authority + ".student";
break;
case COW_STUDENT:
str = itemType + "vnd." + authority + ".student";
break;
case TAB_TEACHER:
str = dirType + "vnd." + authority + ".teacher";
break;
case COW_TEACHER:
str = itemType + "vnd." + authority + ".teacher";
break;
default:
break;
}
return str;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
SQLiteDatabase sqLiteDatabase = sqLiterHelper.getReadableDatabase();
Uri uriReturn = null;
switch (matcher.match(uri)) {
case TAB_STUDENT:
long newStudentId = sqLiteDatabase.insert("student", null, values);
uriReturn = Uri.parse("content://" + authority + "/student/" + newStudentId);
break;
case COW_STUDENT:
break;
case TAB_TEACHER:
long newTeacherId = sqLiteDatabase.insert("teacher", null, values);
uriReturn = Uri.parse("content://" + authority + "/teacher/" + newTeacherId);
break;
case COW_TEACHER:
break;
default:
break;
}
return uriReturn;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
MySQLiteHelper.java代码:
package com.hfut.operationcontentproviderb;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
/**
* author:why
* created on: 2018/11/6 19:10
* description:
*/
public class MySQLiterHelper extends SQLiteOpenHelper {
//数据类型可以有integer,text(文本),real(浮点型),blob(二进制类型)
public static final String createStudentSql = "create table student(" +
"stuID integer primary key autoincrement," +
"name text," +
"age integer," +
"sex text)";
public static final String createTeacherSql = "create table teacher(" +
"name text," +
"teacherID integer," +
"subject text)";
private Context myContext;
public MySQLiterHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
this.myContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(createStudentSql);
db.execSQL(createTeacherSql);
Toast.makeText(myContext, "执行了数据库创建操作", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists student");
db.execSQL("drop table if exists teacher");
onCreate(db);
}
}
activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.hfut.operationcontentproviderb.MainActivity">
<Button
android:id="@+id/btn1"
android:layout_marginTop="30dp"
android:onClick="createStudentTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建表student并初始化数据"
android:textAllCaps="false"
android:textSize="25sp" />
<Button
android:id="@+id/btn2"
app:layout_constraintTop_toBottomOf="@+id/btn1"
android:layout_marginTop="5dp"
android:onClick="createTeacherTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建表teacher并初始化数据"
android:textAllCaps="false"
android:textSize="25sp" />
<TextView
android:id="@+id/dbData"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn2"
android:textSize="25sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
主配置文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hfut.operationcontentproviderb">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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:authorities="com.hfut.operationcontentproviderb"
android:name=".MyProvider"
android:exported="true"
android:enabled="true">
</provider>
</application>
</manifest>
Okay,数据通过方的代码搞定了,我这里为了简化代码,只写查询和增加数据,其他的类似;如何访问其实就和上一篇中一样了,拿着指定的Uri就可以了。下面来看看其代码:
OperationContentProviderA
MainActivity.java代码:
package com.hfut.operationcontentprovidera;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.content.ContentValues;
/**
* @author why
* @date 2018-11-6 20:31:48
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void queryStudentTab(View view) {
Uri uri = Uri.parse("content://com.hfut.operationcontentproviderb/student");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
StringBuilder builder = new StringBuilder();
builder.append(" student表数据:\n");
while (cursor.moveToNext()) {
builder.append("name: " + cursor.getString(cursor.getColumnIndex("name")) +
" age: " + cursor.getInt(cursor.getColumnIndex("age")) +
" sex: " + cursor.getString(cursor.getColumnIndex("sex")) + "\n");
}
((TextView) findViewById(R.id.dbData)).setText(builder.toString());
}
}
public void queryTeacherTab(View view) {
Uri uri = Uri.parse("content://com.hfut.operationcontentproviderb/teacher");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
StringBuilder builder = new StringBuilder();
builder.append(" teacher表数据:\n");
while (cursor.moveToNext()) {
builder.append("name: " + cursor.getString(cursor.getColumnIndex("name")) +
" teacherID: " + cursor.getInt(cursor.getColumnIndex("teacherID")) +
" teacherID: " + cursor.getString(cursor.getColumnIndex("subject")) + "\n");
}
((TextView) findViewById(R.id.dbData)).setText(builder.toString());
}
}
/**
* 添加Tom到student表中
*
* @param view
*/
public void addDataToStudent(View view) {
Uri uri = Uri.parse("content://com.hfut.operationcontentproviderb/student");
ContentValues contentValues = new ContentValues();
StringBuilder builder = new StringBuilder();
builder.append(" 添加数据:\n");
contentValues.put("name", "Tom");
builder.append(" name:Tom ");
contentValues.put("age", 6);
builder.append(" age:6 ");
contentValues.put("sex", "male");
builder.append(" sex:male ");
Uri newUri = getContentResolver().insert(uri, contentValues);
Log.d(TAG, "addDataToStudent: " + newUri.getPathSegments().get(1));
((TextView) findViewById(R.id.dbData)).setText(builder.toString());
}
}
activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.hfut.operationcontentprovidera.MainActivity">
<Button
android:id="@+id/btn1"
android:layout_marginTop="30dp"
android:onClick="queryStudentTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询表student数据"
android:textAllCaps="false"
android:textSize="25sp" />
<Button
android:id="@+id/btn2"
app:layout_constraintTop_toBottomOf="@+id/btn1"
android:layout_marginTop="5dp"
android:onClick="queryTeacherTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询表teacher数据"
android:textAllCaps="false"
android:textSize="25sp" />
<Button
android:id="@+id/btn3"
app:layout_constraintTop_toBottomOf="@+id/btn2"
android:layout_marginTop="5dp"
android:onClick="addDataToStudent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加Tom到student表中"
android:textAllCaps="false"
android:textSize="25sp" />
<TextView
android:id="@+id/dbData"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn3"
android:textSize="25sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
到这里,所有的编码就结束了。
3,效果演示
- 查询数据
- 添加数据
到这里,关于内容提供者的知识就介绍完了。还有几个细节后续会补充一下,今天就到这里了