我们这里先假设先有一个A应用程序,这个程序中存在一个BookStore数据库和一张Book表,
然后还有一个B应用程序,跨程序实现数据共享的意思就是,通过B程序,我们可以对A程序中Book表中的数据进行CRUD(增删改查)操作。
下面我们就一一来实现A应用程序和B应用程序。
A应用程序:DatabaseSave
B应用程序:ProviderTest
我们需要实现ProviderTest应用程序对DatabaseSave应用程序的CRUD操作。
Database项目GitHub地址:
https://github.com/Skymqq/DatabaseSave.git
ProviderTest项目GitHub地址:
https://github.com/Skymqq/ProvidertTest.git
应用程序A(DatabaseSave项目)
我们就直接引用之前创建的DatabaseSave项目文件来继续学习。
如果你没有看过之前的数据库存储项目,可以去GitHub下载一下,项目地址:
https://github.com/Skymqq/DatabaseSave.git
下载之后导入到AS中后,新建一个ContentProvider,步骤如下:
new---》other---》ContentProvider
可以看到,我们将
内容提供器命名为DatabaseProvider
authority指定为com.example.databasesave.provider
Exported属性表示是否允许外部程序访问我们的内容提供器
Enabled属性表示是否启用这个内容提供器。
将两个属性都勾上,点击Finish完成创建。
DatabaseProvider.java代码:
package com.example.administrator.databasesave;
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;
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.example.databasesave.provider";
private static UriMatcher uriMatcher;
private MyDatabaseHelper helper;
static {
//在静态代码块中对UriMatcher进行初始化操作,并将期望匹配的几种URI格式添加进去
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() {
//完成创建、升级 BookStore数据库
helper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
//查询数据
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
cursor = db.query("Book", projection, "id = ?", new String[]{bookId}, null, null, sortOrder);
break;
case CATEGORY_DIR:
cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("Category", projection, "id = ?", new String[]{categoryId}, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
//添加数据
SQLiteDatabase db = helper.getWritableDatabase();
Uri uriReturn = null;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
case BOOK_ITEM:
long newBookId = db.insert("Book", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId = db.insert("Category", null, values);
uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
break;
default:
break;
}
return uriReturn;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
//更新数据
SQLiteDatabase db = helper.getWritableDatabase();
int updateRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
updateRows = db.update("Book", values, selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
updateRows = db.update("Category", values, selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updateRows = db.update("Category", values, "id = ?", new String[]{categoryId});
break;
default:
break;
}
return updateRows;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//删除数据
SQLiteDatabase db = helper.getWritableDatabase();
int deleteRows = 0;
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
deleteRows = db.delete("Book", selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deleteRows = db.delete("Book", "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
deleteRows = db.delete("Category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deleteRows = db.delete("Category", "id = ?", new String[]{categoryId});
break;
default:
break;
}
return deleteRows;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.example.databasesave.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.example.databasesave.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.example.databasesave.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.example.databasesave.provider.category";
}
return null;
}
}
MyDatabaseHelper.java代码:
package com.example.administrator.databasesave;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context context;
public static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
public static final String CREATE_CATEGORY = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)";
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);//执行sql语句创建Book表
db.execSQL(CREATE_CATEGORY);//执行sql语句创建Category表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
AndroidManifest.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.databasesave">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<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:name=".DatabaseProvider"
android:authorities="com.example.databasesave.provider"
android:enabled="true"
android:exported="true"></provider>
</application>
</manifest>
现在这个DatabaseSave项目已经拥有了跨程序共享数据的功能了,再此,我们先将之前运行在模拟器上的DatabaseSave应用卸载,再重新安装应用,以防止之前的项目文件对我们造成干扰。
应用程序B(ProviderTest项目)
下面我们再新建一个ProviderTest项目,我们希望通过这个新建的项目去访问DatabaseSave项目中的数据,从而实现跨程序共享数据的功能。
activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data To Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_query"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query Data From Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete Data From Book"
android:textAllCaps="false"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java代码:
package com.example.administrator.providertest;
import android.content.ContentValues;
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.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button btn_add, btn_query, btn_update, btn_delete;
private String newId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化UI控件
}
private void initView() {
btn_add = (Button) findViewById(R.id.btn_add);
btn_query = (Button) findViewById(R.id.btn_query);
btn_update = (Button) findViewById(R.id.btn_query);
btn_delete = (Button) findViewById(R.id.btn_delete);
btn_add.setOnClickListener(this);
btn_query.setOnClickListener(this);
btn_update.setOnClickListener(this);
btn_delete.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_add:
add();//添加数据
Toast.makeText(this, "add successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_query:
query();//查询数据
Toast.makeText(this, "query successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
update();//更新数据
Toast.makeText(this, "update successfully", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_delete:
delete();//删除数据
Toast.makeText(this, "delete successfully", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
private void add() {
Uri uri = Uri.parse("content://com.example.databasesave.provider/book");
ContentValues cv = new ContentValues();
cv.put("name", "A Clash of Kings");
cv.put("author", "George Martin");
cv.put("pages", 1040);
cv.put("price", 22.85);
Uri newUri = getContentResolver().insert(uri, cv);
newId = newUri.getPathSegments().get(1);
}
private void query() {
Uri uri = Uri.parse("content://com.example.databasesave.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.e(TAG, "book name is " + name);
Log.e(TAG, "book author is " + author);
Log.e(TAG, "book pages are " + pages);
Log.e(TAG, "book price is " + price);
}
cursor.close();
}
}
private void update() {
Uri uri = Uri.parse("content://com.example.databasesave.provider/book/" + newId);
ContentValues cv = new ContentValues();
cv.put("name", "A Storm of Swords");
cv.put("pages", 1216);
cv.put("price", 24.05);
getContentResolver().update(uri, cv, null, null);
}
private void delete() {
Uri uri = Uri.parse("content://com.example.databasesave.provider/book/" + newId);
getContentResolver().delete(uri, null, null);
}
}
运行ProviderTest应用程序:
1.添加数据
在PrioviderTest中点击Add Data To Book按钮向Book表中添加数据
使用adb shell查看Book表中的数据如下:
2.查询数据:
在PrioviderTest中点击Query Data From Book按钮从Book表中查询数据:
ProviderTest中的Logcat将Book表中查询出来的数据打印:
3.更新数据:
在PrioviderTest中点击Update Data 按钮更新Book表中的数据:
Logcat打印:
未更新前的数据:
更新后的数据:
4.删除数据:
在PrioviderTest中点击Delete Data From Book按钮删除Book表中的数据:
adb shell查看Book表中是否还有数据:
说明我们的删除功能也是可以使用的。
跨程序共享数据的CRUD操作,基本上就这些。