内容提供者实现应用访问另一个应用的数据库
实现这么个需求:应用1创建数据库Account.db,应用2对Account.db进行操作
有两个办法。
首先记录第一个不合常理的方法:将创建的数据库的权限改为公开的可读可写的,然后其他应用就可以访问了。当然没人会这么做,太不安全还麻烦。在这里就不详细说了,之提供一个方法可以在代码里写shell命令:
1 public void myChmod() { 2 3 try { 4 String command = "chmod 777 /data/data/com.lgqrlchinese.createprdb/databases/Account.db ";//这里是shell命令,我修改数据库权限为777 5 Runtime runtime = Runtime.getRuntime(); 6 runtime.exec(command); 7 } catch (IOException e) { 8 e.printStackTrace(); 9 } 10 11 }
记录一下作为小白所学的方法。用到内容提供者ContentProvider:
新建一个类MyOpenHelper.java来创建数据库Account.db:
1 package com.lgqrlchinese.createprdb; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteOpenHelper; 6 7 public class MyOpenHelper extends SQLiteOpenHelper { 8 /** 9 * context 上下文 10 * name 数据库名字 11 * factory 游标工厂 12 * version 版本 13 */ 14 public MyOpenHelper(Context context) { 15 super(context, "Account.db", null, 1); 16 } 17 18 @Override 19 public void onCreate(SQLiteDatabase db) { 20 db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),phone varchar(20))"); 21 db.execSQL("insert into info(name,phone) values(?,?)", new String[]{"张三", "17865649855"}); 22 db.execSQL("insert into info(name,phone) values(?,?)", new String[]{"李四", "15364987564"}); 23 24 } 25 26 @Override 27 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 28 29 } 30 }
首先实现在本应用中操作数据库,不妨直接查一查:MainActivity.java:
1 package com.lgqrlchinese.createprdb; 2 3 import android.database.Cursor; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.support.v7.app.AppCompatActivity; 6 import android.os.Bundle; 7 8 import java.io.IOException; 9 10 public class MainActivity extends AppCompatActivity { 11 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.activity_main); 16 17 MyOpenHelper myOpenHelper = new MyOpenHelper(getApplicationContext()); 18 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); 19 Cursor cursor = db.query("info", null, null, null, null, null, null); 20 if (cursor != null && cursor.getCount() > 0) { 21 while (cursor.moveToNext()) { 22 String name = cursor.getString(1); 23 String phone = cursor.getString(2); 24 System.out.println(name + phone); 25 } 26 } 27 28 } 29 30 }
只是检验下数据库有木有问题,通过检测,没有问题,然后我们开始写内容提供者AccountContentProvider.java,其中有四个方法正好是对数据库的四个操作:增删改查。
1 package com.lgqrlchinese.createprdb; 2 3 import android.content.ContentProvider; 4 import android.content.ContentValues; 5 import android.content.UriMatcher; 6 import android.database.Cursor; 7 import android.database.sqlite.SQLiteDatabase; 8 import android.net.Uri; 9 10 public class AccountContentProvider extends ContentProvider { 11 //定义一个uriMathcher,路径匹配器 12 private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 13 14 private static final int QUERYSUCESS = 0; 15 private static final int INSERTSUCESS = 0; 16 private static final int UPDATESUCESS = 0; 17 private static final int DELETESUCESS = 0; 18 19 //静态代码块,添加匹配规则 20 static { 21 /** 22 * authority 注意和清单文件里面配置的一样 23 * path 24 * code 一个常量 25 */ 26 sURIMatcher.addURI("AccountContentProvider", "query", QUERYSUCESS); 27 sURIMatcher.addURI("AccountContentProvider", "insert", INSERTSUCESS); 28 sURIMatcher.addURI("AccountContentProvider", "update", UPDATESUCESS); 29 sURIMatcher.addURI("AccountContentProvider", "delete", DELETESUCESS); 30 31 } 32 33 private MyOpenHelper myOpenHelper; 34 35 public AccountContentProvider() { 36 } 37 38 @Override 39 public boolean onCreate() { 40 // TODO: Implement this to initialize your content provider on startup. 41 42 myOpenHelper = new MyOpenHelper(getContext()); 43 44 return false; 45 } 46 47 @Override 48 public int delete(Uri uri, String selection, String[] selectionArgs) { 49 // Implement this to handle requests to delete one or more rows. 50 int code = sURIMatcher.match(uri); 51 if (code == DELETESUCESS) { 52 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); 53 int delete = db.delete("info", selection, selectionArgs); 54 return delete; 55 } else { 56 throw new IllegalArgumentException("delete您的路径不匹配,请检查路径"); 57 58 } 59 } 60 61 @Override 62 public String getType(Uri uri) { 63 // TODO: Implement this to handle requests for the MIME type of the data 64 // at the given URI. 65 throw new UnsupportedOperationException("Not yet implemented"); 66 } 67 68 @Override 69 public Uri insert(Uri uri, ContentValues values) { 70 // TODO: Implement this to handle requests to insert a new row. 71 int code = sURIMatcher.match(uri); 72 if (code == INSERTSUCESS) { 73 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); 74 long insert = db.insert("info", null, values); 75 Uri uri2 = Uri.parse("com.lgqrlchinese.insert" + insert); 76 return uri2; 77 } else { 78 throw new IllegalArgumentException("insert您的路径不匹配,请检查路径"); 79 80 } 81 } 82 83 @Override 84 public Cursor query(Uri uri, String[] projection, String selection, 85 String[] selectionArgs, String sortOrder) { 86 // TODO: Implement this to handle query requests from clients. 87 int code = sURIMatcher.match(uri); 88 if (code == QUERYSUCESS) { 89 //路径匹配成功,把query方法实现(数据库查询方法),造作数据库必须获得SQLiteDatabase对象 90 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); 91 Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder); 92 //cursor不能关闭 93 return cursor; 94 95 96 } else { 97 //路径不匹配 98 throw new IllegalArgumentException("您的路径不匹配,请检查路径"); 99 } 100 } 101 102 @Override 103 public int update(Uri uri, ContentValues values, String selection, 104 String[] selectionArgs) { 105 // TODO: Implement this to handle requests to update one or more rows. 106 int code = sURIMatcher.match(uri); 107 if (code == UPDATESUCESS) { 108 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); 109 int update = db.update("info", values, selection, selectionArgs); 110 return update; 111 } else { 112 throw new IllegalArgumentException("update您的路径不匹配,请检查路径"); 113 114 } 115 } 116 }
当然要在清单文件中配置内容提供者
1 <provider 2 android:name=".AccountContentProvider" 3 android:authorities="AccountContentProvider" 4 android:enabled="true" 5 android:exported="true"> 6 </provider>
此时新建一个项目,开始第二个应用
在布局文件activity_main.xml中加入四个按钮分别是增删改查:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical" 7 tools:context=".MainActivity"> 8 9 <Button 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:onClick="click1" 13 android:text="add" /> 14 15 <Button 16 android:layout_width="wrap_content" 17 android:layout_height="wrap_content" 18 android:onClick="click2" 19 android:text="delete" /> 20 21 <Button 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:onClick="click3" 25 android:text="update" /> 26 27 <Button 28 android:layout_width="wrap_content" 29 android:layout_height="wrap_content" 30 android:onClick="click4" 31 android:text="query" /> 32 33 </LinearLayout>
在MainActivity.java中实现按钮的点击事件:
1 package com.lgqrlchinese.readdb; 2 3 import android.content.ContentValues; 4 import android.database.Cursor; 5 import android.database.sqlite.SQLiteDatabase; 6 import android.net.Uri; 7 import android.support.v7.app.AppCompatActivity; 8 import android.os.Bundle; 9 import android.view.View; 10 import android.widget.Toast; 11 12 public class MainActivity extends AppCompatActivity { 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 19 } 20 21 //add 22 public void click1(View view) { 23 Uri uri = Uri.parse("content://AccountContentProvider/insert");//路径和定义的路径一样 24 ContentValues values = new ContentValues(); 25 /** 26 * key 字段名 27 * name 值 28 */ 29 values.put("name", "赵六"); 30 values.put("phone", "15445896458"); 31 Uri insert = getContentResolver().insert(uri, values); 32 System.out.println("insert:" + insert); 33 34 35 } 36 37 //delete 38 public void click2(View view) { 39 Uri uri = Uri.parse("content://AccountContentProvider/delete");//路径和定义的路径一样 40 int delete = getContentResolver().delete(uri, "name=?", new String[]{"赵六"}); 41 Toast.makeText(getApplicationContext(), "删除了" + delete + "行", Toast.LENGTH_SHORT).show(); 42 43 44 } 45 46 //update 47 public void click3(View view) { 48 Uri uri = Uri.parse("content://AccountContentProvider/update");//路径和定义的路径一样 49 ContentValues values = new ContentValues(); 50 values.put("phone", 10086); 51 int update = getContentResolver().update(uri, values, "name=?", new String[]{"张三"}); 52 Toast.makeText(getApplicationContext(), "更改了" + update + "行", Toast.LENGTH_SHORT).show(); 53 54 } 55 56 //query 57 public void click4(View view) { 58 //拿到内容解析者,直接通过上下文拿取 59 Uri uri = Uri.parse("content://AccountContentProvider/query");//路径和定义的路径一样 60 Cursor cursor = getContentResolver().query(uri, null, null, null, null); 61 if (cursor != null && cursor.getCount() > 0) { 62 while (cursor.moveToNext()) { 63 String name = cursor.getString(1); 64 String phone = cursor.getString(2); 65 System.out.println("应用二" + name + phone); 66 67 } 68 } 69 } 70 }
这样就实现了第二个应用访问第一个应用的数据库。
昔日我曾苍老,如今风华正茂(ง •̀_•́)ง