android——实现跨程序访问数据
使用之前的SQLite存储的应用程序。首先需要在这个应用程序中创建内容提供器,右击com.example.administrator.exp7包→New→Other→Content Provider,会弹出这样的对话框,
其中Class name 是内容提供器的名字,Authorities是包名com.example.administrator.exp7,Exported表示是否允许外部程序访问内容提供器,Enabled表示是否启用这个内容提供器。
然后修改MyContentProvider中的代码:
1 public class MyContentProvider extends ContentProvider { 2 //用于识别URI的自定义代码 3 public static final int BOOK_DIR = 0; 4 5 public static final int BOOK_ITEM = 1; 6 7 public static final int CATEGORY_DIR = 2; 8 9 public static final int CATEGORY_ITEM = 3; 10 11 public static final String AUTHORITY = "com.example.administrator.exp7"; 12 13 private MyDatabaseHelper dbHelper; 14 15 //创建UriMatcher的实例 16 private static UriMatcher uriMatcher; 17 18 //将自定义代码和希望的URI匹配 19 static { 20 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 21 uriMatcher.addURI(AUTHORITY,"book",BOOK_DIR); 22 uriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM); 23 uriMatcher.addURI(AUTHORITY,"category",CATEGORY_DIR); 24 uriMatcher.addURI(AUTHORITY,"category/#",CATEGORY_ITEM); 25 26 } 27 @Override 28 /* 29 初始化时调用 30 通常会在这里完成对数据库的创建和升级等操作,返回true表示初始化成功。 31 只有当存在ContentResolver尝试访问程序中的数据时,才会进行初始化。 32 */ 33 public boolean onCreate() { 34 dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null , 2); 35 return true; 36 } 37 38 /* 39 查询数据 40 uri 确定查询的是那一张表 41 projection 查询那一列 42 selection 和 selectionArgs查询那些行 43 sortOrder 对结果进行排序 44 返回的数据存放在Cursor对象中 45 */ 46 @Override 47 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 48 49 SQLiteDatabase db = dbHelper.getReadableDatabase(); 50 Cursor cursor = null; 51 52 //判断希望被访问的数据是什么数据 53 switch (uriMatcher.match(uri)){ 54 case BOOK_DIR: 55 //查询table1表中的所有数据 56 cursor = db.query("Book",projection, selection, selectionArgs,null ,null,sortOrder); 57 break; 58 case BOOK_ITEM: 59 //查询table1表中的单条数据 60 String bookId = uri.getPathSegments().get(1); 61 cursor = db.query("Book",projection, "id = ?", new String[] { bookId },null ,null,sortOrder); 62 break; 63 case CATEGORY_DIR: 64 cursor = db.query("Category",projection, selection, selectionArgs,null ,null,sortOrder); 65 break; 66 case CATEGORY_ITEM: 67 //查询table2表中的单条数据 68 String categoryId = uri.getPathSegments().get(1); 69 cursor = db.query("Category",projection, "id = ?", new String[] { categoryId },null ,null,sortOrder); 70 break; 71 default: 72 break; 73 } 74 return cursor; 75 } 76 77 /* 78 根据传入的数据URI来返回相应的MIME类型 79 */ 80 @Override 81 public String getType(Uri uri) { 82 83 switch (uriMatcher.match(uri)){ 84 case BOOK_DIR: 85 return "vnd.android.cursor.dir/vnd.com.example.administrator.exp7.provider.book"; 86 case BOOK_ITEM: 87 return "vnd.android.cursor.item/vnd.com.example.administrator.exp7.provider.book"; 88 case CATEGORY_DIR: 89 return "vnd.android.cursor.dir/vnd.com.example.administrator.exp7.provider.category"; 90 case CATEGORY_ITEM: 91 return "vnd.android.cursor.item/vnd.com.example.administrator.exp7.provider.category"; 92 default: 93 break; 94 } 95 return null; 96 } 97 /* 98 添加数据 99 uri 确定添加的是那一张表 100 values 保存待添加的数据 101 返回一条表示这条新记录的URI 102 */ 103 @Override 104 public Uri insert(Uri uri, ContentValues values) { 105 106 SQLiteDatabase db = dbHelper.getWritableDatabase(); 107 Uri uriReturn = null; 108 109 //判断希望被增加的数据是那个表的 110 switch (uriMatcher.match(uri)){ 111 112 case BOOK_DIR: 113 case BOOK_ITEM: 114 long newBookId = db.insert("Book",null,values); 115 uriReturn = Uri.parse("content://"+ AUTHORITY + "/book/" + newBookId); 116 break; 117 case CATEGORY_DIR: 118 case CATEGORY_ITEM: 119 long newCategoryId = db.insert("Category",null,values); 120 uriReturn = Uri.parse("content://"+ AUTHORITY + "/category/" + newCategoryId); 121 break; 122 default: 123 break; 124 } 125 return uriReturn; 126 } 127 /* 128 删除数据 129 selection 和 selectionArgs 删除那些行 130 返回被删除的行数 131 */ 132 @Override 133 public int delete(Uri uri, String selection, String[] selectionArgs) { 134 SQLiteDatabase db = dbHelper.getWritableDatabase(); 135 int deletedRows = 0; 136 137 switch (uriMatcher.match(uri)){ 138 case BOOK_DIR: 139 deletedRows = db.delete("Book", selection, selectionArgs); 140 break; 141 case BOOK_ITEM: 142 String bookId = uri.getPathSegments().get(1); 143 deletedRows = db.delete("Book", "id = ?", new String[] { bookId }); 144 break; 145 case CATEGORY_DIR: 146 deletedRows = db.delete("Category",selection, selectionArgs); 147 break; 148 case CATEGORY_ITEM: 149 String categoryId = uri.getPathSegments().get(1); 150 deletedRows = db.delete("Category","id = ?", new String[] { categoryId }); 151 break; 152 default: 153 break; 154 } 155 return deletedRows; 156 } 157 /* 158 更新已有的数据 159 uri 确定更新的是那一张表 160 values 新数据 161 selection 和 selectionArgs 更新那些行 162 会返回更新的行数 163 */ 164 @Override 165 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 166 167 SQLiteDatabase db = dbHelper.getWritableDatabase(); 168 int updatedRows = 0; 169 170 switch (uriMatcher.match(uri)){ 171 172 case BOOK_DIR: 173 updatedRows = db.update("Book", values, selection, selectionArgs); 174 break; 175 case BOOK_ITEM: 176 String bookId = uri.getPathSegments().get(1); 177 updatedRows = db.update("Book", values, "id = ?", new String[] { bookId }); 178 break; 179 case CATEGORY_DIR: 180 updatedRows = db.update("Category", values, selection, selectionArgs); 181 break; 182 case CATEGORY_ITEM: 183 String categoryId = uri.getPathSegments().get(1); 184 updatedRows = db.update("Category", values, "id = ?", new String[] { categoryId }); 185 break; 186 default: 187 break; 188 } 189 return updatedRows; 190 } 191 }
先看onCreate()方法完成了数据库的创建或升级,创建了一个MyDatabaseHelper 的实例dbHelper,并返回true。
然后是用于查询的query函数,先通过dbHelper.getReadableDatabase()方法获得可以操作数据库的SQLiteDatabase 对象的实例db,根据传入的Uri判断希望被访问的数据是哪一张表,在调用SQLiteDatabase 的query()方法进行查询,这里还使用了uri.getPathSegments().get(1),这个方法会将内容URI权限后的部分以"/"进行分割,第一个"/"之前的可用get(0)获得,这次想要获得的id要使用get(1)获得。
insert()方法先使用Uri判断想要添加的数据是哪一张表,然后调用SQLiteDatabase 的insert()方法在相应的表中添加数据,这个方法会返回添加的数据的Id,然后使用Uri.parse()方法讲一个内容URI解析成一个Uri对象,这个对象是以id结尾的。
delete()也是先先通过dbHelper.getReadableDatabase()方法获得可以操作数据库的SQLiteDatabase 对象的实例db,然后根据传入的Uri判断希望被访问的数据是哪一张表,在调用SQLiteDatabase 的delete()进行删除,被删除的行数作为返回值返回。
updata()也是类似,区别就是调用SQLiteDatabase 的updata()方法进行更新,受影响的行数会作为返回值返回。
以上是数据被访问的应用com.example.administrator.exp7的内容适配器的代码。
然后是读取数据的应用程序,先是布局文件的编写,有四个按钮执行添加、查询、更新、删除的功能。
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 8 <Button 9 android:id="@+id/add_data" 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:text="新增数据" /> 13 14 <Button 15 android:id="@+id/query_data" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:text="查询数据" /> 19 20 <Button 21 android:id="@+id/updata_data" 22 android:layout_width="match_parent" 23 android:layout_height="wrap_content" 24 android:text="更新数据" /> 25 26 <Button 27 android:id="@+id/delete_data" 28 android:layout_width="match_parent" 29 android:layout_height="wrap_content" 30 android:text="删除数据" /> 31 </LinearLayout>
然后修改MainActivity中的代码:
1 public class MainActivity extends AppCompatActivity { 2 3 private String newId; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 //注册按钮 11 Button addData = (Button) findViewById(R.id.add_data); 12 Button queryData = (Button) findViewById(R.id.query_data); 13 Button updataData = (Button) findViewById(R.id.updata_data); 14 Button deleteData = (Button) findViewById(R.id.delete_data); 15 16 17 //添加数据 18 addData.setOnClickListener(new View.OnClickListener() { 19 @Override 20 public void onClick(View v) { 21 Uri uri = Uri.parse("content://com.example.administrator.exp7/book"); 22 ContentValues values = new ContentValues(); 23 values.put("name", "a book name"); 24 values.put("author", "a book author"); 25 values.put("pages", 1000); 26 values.put("price",22); 27 Uri newUri = getContentResolver().insert(uri,values); 28 newId = newUri.getPathSegments().get(1); 29 } 30 }); 31 32 //查询数据 33 queryData.setOnClickListener(new View.OnClickListener() { 34 @Override 35 public void onClick(View v) { 36 Uri uri = Uri.parse("content://com.example.administrator.exp7/book"); 37 Cursor cursor = getContentResolver().query(uri, null, null, null, null); 38 39 //输出数据 40 if(cursor != null){ 41 while (cursor.moveToNext()){ 42 String name = cursor.getString(cursor.getColumnIndex("name")); 43 String author = cursor.getString(cursor.getColumnIndex("author")); 44 int pages = cursor.getInt(cursor.getColumnIndex("pages")); 45 double price = cursor.getDouble(cursor.getColumnIndex("price")); 46 Log.d("MainActivity","name is "+ name); 47 Log.d("MainActivity","author is "+ author); 48 Log.d("MainActivity","pages is "+ pages); 49 Log.d("MainActivity","price is "+ price); 50 Log.d("MainActivity"," newId is "+ newId); 51 } 52 cursor.close(); 53 } 54 } 55 }); 56 57 //更新数据 58 updataData.setOnClickListener(new View.OnClickListener() { 59 @Override 60 public void onClick(View v) { 61 Uri uri = Uri.parse("content://com.example.administrator.exp7/book/" + newId); 62 ContentValues values = new ContentValues(); 63 values.put("name", "other name"); 64 values.put("pages", 2200); 65 values.put("price",21); 66 getContentResolver().update(uri,values,null,null); 67 } 68 }); 69 70 //删除数据 71 deleteData.setOnClickListener(new View.OnClickListener() { 72 @Override 73 public void onClick(View v) { 74 Uri uri = Uri.parse("content://com.example.administrator.exp7/book/" + newId); 75 getContentResolver().delete(uri, null,null); 76 } 77 }); 78 79 } 80 }
添加数据的时候,先调用Uri.parse()方法将URI语句解析成Uri对象,将数据存储在ContentValuesd的对象中,然后调用getContentResolver().insert()方法执行添加数据的操作,会返回一个Uri对象,然后使用newUri.getPathSegments().get(1)得到刚刚添加数据的id。
查询数据时一样,先解析URI语句,然后使用getContentResolver().query()方法进行查询操作,将数据存储在cursor对象中,然后在遍历cursor将查询到的数据输出出来。
更新数据的时候,先解析URI语句,这里的URI语句中含有刚刚添加的数据的id就是更新刚刚添加的数据,同样将要更新数据存储在ContentValuesd的对象中。再调用getContentResolver().update()进行更新数据的操作。
删除数据调用getContentResolver().delete()进行删除操作。