標籤:sql uri android content provider getcontentresolver
ContentProvider:內容提供者
1、為儲存和讀取資料提供了統一的介面
2、使用ContentProvider,應用程式可以實現資料共用
3、android內建的許多資料都是使用ContentProvider形式,供開發人員調用的(如視頻,音頻,圖片,通訊錄等)
4、當應用繼承ContentProvider類,並重寫該類用於提供資料和儲存資料的方法,就可以向其他應用共用其資料。
先來瞭解一下Uri:
Uri,即通用資源標識符
1、Uri代表要操作的資料,Android上可用的每種資源 - 映像、視頻片段等都可以用Uri來表示
2、Uri一般由三部分組成:訪問資源的命名機制;存放資源的主機名稱; 資源自身的名稱,由路徑表示。
Android的Uri由以下三部分組成: "content://"+資料的路徑+標示ID(可選)、
如:所有連絡人的Uri: content://contacts/people
某個連絡人的Uri: content://contacts/people/5 //連絡人中id為5的連絡人
3、如果要把一個字串轉換成Uri,可以使用Uri類中的parse()方法,如下:
Uri uri = Uri.parse("content://com.archer.ContentProvider")
ContentResolver:
在android中,每個應用程式是可以實現資料共用的,對於每一個應用程式程式都擁有一個ContentProvider執行個體進行儲存,
而ContentResolver則是用於管理所有程式的ContentProvider執行個體,通過ContentRescolver可以對資料進行添加、刪除、修改和查詢操作
通過getContentRescolver()擷取執行個體
下面通過建立一個Content Provider,並使用 SQLLite資料庫實現資料共用
首先,定義ContentProvider的CONTENT_URI,並且是public static final的Uri類型的類變數
必須為其制定一個唯一的字串值,一般用類的全名稱命名
package com.ContentProviderDemo.Archer;import android.net.Uri;import android.provider.BaseColumns;public class MyUsers {public static final String AUTHORITY = "com.archer.ContentProvider";//BaseColumn類中已經包含了 _id 欄位public static final class User implements BaseColumns{public static final Uri CONTENT_URI =Uri.parse("content://com.archer.ContentProvider");//表資料列public static final String USER_NAME = "USER_NAME";}}
之後建立一個類繼承ContentProvider
package com.ContentProviderDemo.Archer;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.database.sqlite.SQLiteQueryBuilder;import android.net.Uri;public class MyContentProvider extends ContentProvider{/** * 定義一個SQLiteDatabase變數 * Android提供了一個名為SQLiteDatabase的類,它封裝了一些操作資料庫的API。 * 使用它能實現基本的CRUD(插入、查詢、更新、刪除)操作,通過getWritableDatabase()和getReadableDatabase()可以擷取資料庫執行個體 */private SQLiteDatabase sqlDB;private DatabaseHelper dbHelper;private static final String DATABASE_NAME = "Users.db"; //資料庫名private static final int DATABASE_VERSION = 1; //資料庫版本//表名private static final String TABLE_NAME = "User";//表名/** * 首先需要建立資料庫(定義一個內部類,繼承SQLiteOpenHelper類,重寫其方法) * SQliteOpenHelper是一個抽象類別,來管理資料庫的建立和版本的管理。 * 要使用它必須實現它的onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int)方法 * onCreate:當資料庫第一次被建立的時候被執行,例如建立表,初始化資料等。 * onUpgrade:當資料庫需要被更新的時候執行,例如刪除舊錶,建立新表。 * @author Administrator */private static class DatabaseHelper extends SQLiteOpenHelper{/*** 建立資料庫的構造方法* name 資料庫的名字* factory 查詢資料庫的遊標工廠一般情況下用sdk預設的* version 資料庫的版本一般大於0*/public DatabaseHelper(Context context){super(context,DATABASE_NAME,null,DATABASE_VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {String sq1 = "Create table " + TABLE_NAME + "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);"; //建立表的sql語句db.execSQL(sq1); //建立表}/*** 更新資料的時候調用的方法,如新增表、修改資料*/@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {//增加一列db.execSQL("DROP TABLE IF EXISTS" + TABLE_NAME);onCreate(db);}}@Overridepublic int delete(Uri uri, String s, String[] arg2) {return 0;}@Overridepublic String getType(Uri arg0) {return null;}/** * 插入資料 * ContentValues類負責儲存一些名值對,的名是一個String類型,而值都是基本類型。 */@Overridepublic Uri insert(Uri uri, ContentValues contentValues) {//以讀寫方式開啟資料庫,一旦資料庫的磁碟空間滿了,資料庫就只能讀而不能寫,就會開啟失敗sqlDB = dbHelper.getWritableDatabase(); //插入一條新的紀錄,如果插入成功則會返回這條記錄的id,如果插入失敗會返回-1long rowId = sqlDB.insert(TABLE_NAME, "", contentValues);if(rowId > 0){ // ContentUris 類用於擷取Uri路徑後面的ID部分 //appendId:為該Uri加上IDUri rowUri = ContentUris.appendId(MyUsers.User.CONTENT_URI.buildUpon(), rowId).build(); // getContextResolver().notifyChange():獲得一個ContextResolver對象並且更新裡面的內容。getContext().getContentResolver().notifyChange(rowUri, null);return rowUri;}throw new SQLException("Fail to insert row into"+uri);}/** * 這是一個回呼函數,當產生所在類的對象時,這個方法被調用,建立一個資料庫 */@Overridepublic boolean onCreate() {dbHelper = new DatabaseHelper(getContext());return (dbHelper == null) ? false:true;}/** * 查詢 */@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder) {//SQLiteQueryBuilder 是一個構造SQL查詢語句的輔助類。SQLiteQueryBuilder qb = new SQLiteQueryBuilder();//getReadableDatabase():先以讀寫方式開啟資料庫,如果資料庫的磁碟空間滿了,就會開啟失敗,當開啟失敗後會繼續嘗試以唯讀方式開啟資料庫SQLiteDatabase db = dbHelper.getReadableDatabase();qb.setTables(TABLE_NAME);/** * Cursor 是每行的集合 * 在Android中 查詢資料是通過Cursor 類來實現的。當我們使用 SQLiteDatabase.query()方法時,就會得到Cursor對象, * Cursor所指向的就是每一條資料 */Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder);c.setNotificationUri(getContext().getContentResolver(), uri);return c;}@Overridepublic int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {return 0;}}
在AndroidManifest.xml中進行註冊:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".MyContentProvider" android:authorities="com.archer.ContentProvider"> </provider> <!-- android:authorities屬性配置的就是該ContentProvider的名字,是它在Android系統中的名字,我們是通過這個名字去找對應的ContentProvider對象的--> </application>
最後,建立一個新的工程(測試用)
package com.ContentProviderDemo.Archer;import android.app.Activity;import android.content.ContentValues;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.util.Log;/** * 在另一個工程中訪問建立的資料庫,不用再註冊provider,否則會儲存 * @author Administrator * */public class MainActivity extends Activity {public static final String AUTHORITY = "com.archer.ContentProvider";private Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);insertRecord("record1");displayRecords(); }//插入資料private void insertRecord(String userName) {ContentValues values = new ContentValues();values.put("USER_NAME", userName);getContentResolver().insert(CONTENT_URI, values);}//查詢資料private void displayRecords() {// 該數組中包含了所有要返回的欄位String columns[] = new String[] { "_id", "USER_NAME" };Uri myUri = CONTENT_URI;Cursor cur = getContentResolver().query(myUri, columns, null, null,null);if (cur.moveToFirst()) {String id = null;String userName = null;do {id = cur.getString(cur.getColumnIndex("_id"));userName = cur.getString(cur.getColumnIndex("USER_NAME"));Log.e("TAG", "id:" + id + ";" + "userName:" + userName);} while (cur.moveToNext());}cur.close(); // 關閉Cursor對象}}
這樣,就是先不同應用程式間的資料共用了
Android四大組件之Content Provider