目标:A程序提供外部访问接口
B程序通过这个接口来访问A程序上面的数据(增删查改)
因为所有的增删查改操作都是需要匹配到想的内容URI格式才能进行的,而我们在写接口的时候自然不会在其添加隐私数据,所以这部分数据无法被外部程序访问到。
下面上实例(A程序)
1、新建类去继承ContentProvider来创建一个自己的内容提供器,ContentProvider中有6个抽象方法,我们在使用子类集成的时候需要重写这6个方法,在A程序新建DatabaseProvider继承自ContentProvider:
2、借助UriMatcher这个类实现匹配内容URI的功能。
3、getType()这个方法比较陌生,该方法用于获取URI对象所对应的MIME类型。
4、AndroidManifest中添加provider
<provider
android:authorities="com.superxingyun.mydatabasehelper.provider"
android:name="com.superxingyun.mydatabasehelper.DatabaseProvider"
android:exported="true"/>
DatabaseProvider.class:
package com.superxingyun.mydatabasehelper;
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 android.support.annotation.Nullable;
/*
* Created by 月满轩尼诗 on 2016/10/21.
*/
public class DatabaseProvider extends ContentProvider {
public static final int BOOK_DIR = 0;
public static final int BOOK_ITEM = 1;
public static final int CATEGORY_DIR = 2;
public static final int CATEGORY_ITEM = 3;
public static final String AUTHORITY = "com.superxingyun.mydatabasehelper.provider";
private static UriMatcher uriMatcher;
private MyDatabaseHelper dbHelper;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
}
@Override
public boolean onCreate() {
dbHelper = new MyDatabaseHelper(getContext(), "BookStore,db", null, 2);
return true;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
//查询数据
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
cursor = db.query("Book", strings, s, strings1, null, null, s1);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
cursor = db.query("Book", strings1, "id = ?", new String[]{bookId}, null, null, s1);
break;
case CATEGORY_DIR:
cursor = db.query("Category", strings, s, strings1, null, null, s1);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("Category", strings, "id = ?", new String[] { categoryId }, null, null, s1);
break;
}
return cursor;
}
@Nullable
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.superxingyun.mydatabasehelper.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.superxingyun.mydatabasehelper.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.superxingyun.mydatabasehelper.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.superxingyun.mydatabasehelper.provider.category";
}
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
//添加数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
Uri uri1 = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
case BOOK_ITEM:
long newBookId = db.insert("Book", null, contentValues);
uri1 = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId = db.insert("Category", null, contentValues);
uri1 = Uri.parse("content://" + AUTHORITY + "/category/" +newCategoryId);
break;
default:
break;
}
return uri1;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
//删除数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
int deletedRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
deletedRows = db.delete("Book", s, strings);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deletedRows = db.delete("Book", "id = ?", new String[] { bookId });
break;
case CATEGORY_DIR:
deletedRows = db.delete("Category", s, strings);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deletedRows = db.delete("Category", "id = ?", new String[] { categoryId });
break;
default:
break;
}
return deletedRows;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
//更新数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
int updatedRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
updatedRows = db.update("Book", contentValues, s, strings);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
updatedRows = db.update("Book", contentValues, "id = ?", new String[] { bookId });
break;
case CATEGORY_DIR:
updatedRows = db.update("Category", contentValues, s ,strings);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updatedRows = db.update("Category", contentValues, "id = ?", new String[] { categoryId });
break;
}
return updatedRows;
}
}
B程序:
MainActivity.class:
package com.superxingyun.providertest;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private String newId;
@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) {
//添加数据
Uri uri = Uri.parse("content://com.superxingyun.mydatabasehelper.provider/book");
ContentValues values = new ContentValues();
values.put("name", "A * of Kings");
values.put("author", "George Martin");
values.put("pages", 1040);
values.put("price", 22.85);
Uri newUri = getContentResolver().insert(uri, values);
newId = newUri.getPathSegments().get(1);
}
});
Button queryData = (Button) findViewById(R.id.query_data);
queryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//查询数据
Uri uri = Uri.parse("content://com.superxingyun.mydatabasehelper.provider/book");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity", "book name is:" + name);
Log.d("MainActivity", "book author is:" + author);
Log.d("MainActivity", "book pages is:" + pages);
Log.d("MainActivity", "book price is:" + price);
}
//关闭游标
cursor.close();
}
}
});
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//更新数据
Uri uri = Uri.parse("content://com.superxingyun.mydatabasehelper.provider/book/" + newId);
ContentValues values = new ContentValues();
values.put("name", "A Storm of Swords");
values.put("pages", 1216);
values.put("price", 24.05);
getContentResolver().update(uri, values, null, null);
}
});
Button deleteData = (Button) findViewById(R.id.deldet_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//删除数据
Uri uri = Uri.parse("content://com.superxingyun.mydatabasehelper.provider/book/" + newId);
getContentResolver().delete(uri, null, null);
}
});
}
}
界面是4个按钮,分别是对之前A程序的数据进行增删查改,每个按钮的逻辑也在代码里面了。下面运行,程序B(在此之前需要将程序A在模拟器上先删除,以免残留数据造成干扰,但是记得在运行一下A程序,不然手机上没有A程序,B在访问接口的时候会报错,当时我就遇到了这个问题)。点击add按钮时,回想book表中添加一行数据,此时在点击query按钮就会将数据打印出来
然后我们再次点击update按钮,在点击查询,发现出具发生了变化,说明更新数据也完成了
最后,点击delete这一条数据就会被删除,点击查询也不会出现任何内容,这里有同学或许会有疑惑,是如何知道是哪一条数据呢,会不会删除所有的数据呀,其实在开始的时候我们定义了一个newId这个字符串常量再做更新、删除数据操作时有指定。在插入数据时newId = newUri.getPathSegments().get(1);,因为insert方法会返回一个Uri对象,这个对象中包含了刚刚增加的这条数据的id然后通过这个方法给他取出来,在之后的内容URI
Uri uri = Uri.parse(“content://com.superxingyun.mydatabasehelper.provider/book/” + newId);
后面的尾部添加了一个id,二这个id正是我们添加数据的时候返回的那一条数据所对应的 id,因为有了这个所有更新和删除就只有这一条数据受到影响,book表中其他的数据不会受到影响。
现在,任何一个程序都可以访问我们A程序中的数据了。