ContentProvider:自定義的應用

//繼承ContentProvider的自定義類
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

import com.example.Sqlutil.MySqliteOpenHelper;

//如下代碼是繼承ContentProvider類用它裏面的增刪改查方法,其餘應用操做時就是調用這裏的方法
/*在清單文件中聲明註冊 ContentProvider ://在<activity>裏面配置
 <provider android:name=".MyWordsProvider"
 android:authorities="com.steven.wordscontentprovider"
 android:exported="true"
 />
 //android:name 屬性的值是: 繼承ContentProvider 類的子類的完整路徑;
 //android:authorities 屬性的值是: content:URI 中 authority 部分。通常就是將 name 屬性的值全小寫,能夠本身寫,但要記住。
 //android:exported 屬性是否容許其餘應用調用。若是是 false ,則該 ContentProvider 不容許其餘應用調用
 */
public class MyContentProvider extends ContentProvider {
	// authorties功能清單中您配置暴露給其餘應用使用的屬性名字
	private static String authorties = "com.example.providercustomUtils.mycontentprovider";
	private MySqliteOpenHelper openHelper;// 繼承SQLiteOpenHelper的類
	private static UriMatcher matcher;// 匹配器/匹配類:當外部應用調用它內部的方法時,要匹配外部應用傳進來的uri
	private static final int MATCH_STUDENT = 110;
	private static final int MATCH_NAME = 119;
	private static final int MATCH_SCORE = 120;
	static {// 靜態代碼塊只執行一次
		matcher = new UriMatcher(UriMatcher.NO_MATCH);// 若是uri不匹配,即不正確時 ,返回-1;
		// 第一個參數:uri中authorties,第二個參數:path路徑,建議寫上表名;第三個:匹配正確的返回值(自定義的值)
		// matcher.addURI(authority, path, code),能夠寫多個matcher
		matcher.addURI(authorties, "studentinfo", MATCH_STUDENT);
		matcher.addURI(authorties, "studentinfo/*", MATCH_NAME);
		matcher.addURI(authorties, "studentinfo_id/#", MATCH_SCORE);
		// 注意:文本跟數字matcher都存在時,path所取的名字要不一樣,/*這個是文本標誌,/#個是數字的標誌
	}

	// 如下只用到一個Uri
	@Override
	// 首次訪問執行一次,作初始化的操做,好比去繼承SQLiteOpenHelper的類去執行建表或數據庫操做等
	public boolean onCreate() {
		openHelper = new MySqliteOpenHelper(getContext());
		return false;
	}

	// openHelper.getReadableDatabase() : 若是空間不足,不能寫,只能讀
	// openHelper.getWritableDatabase(); 若是空間不足,既不能寫,也不能讀(報錯)
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// 查詢首先用一個Switch,由於有多個mathcer時有多個操做
		Cursor cursor = null;
		SQLiteDatabase db = openHelper.getReadableDatabase();
		switch (matcher.match(uri)) {
		// 路徑正確時,返回匹配正確的值,就查詢
		case MATCH_STUDENT:
			cursor = db.query("studentinfo", projection, selection,
					selectionArgs, null, null, sortOrder);
			break;

		case MATCH_NAME:
			String name = uri.getLastPathSegment();// 獲取URI最後的文本,即傳過來的文字,字符等
			cursor = db.query("studentinfo", projection, "sname like ?",
					new String[] { name + "%" }, null, null, null);// 模糊查詢
			break;
		case MATCH_SCORE:
			long score = ContentUris.parseId(uri);
			// 數字跟uri獲取id的方式同樣獲取,不能像上面uri.getLastPathSegment()那樣操做了
			cursor = db.query("studentinfo", projection, "score=?",
					new String[] { score + "" }, null, null, null);
			break;
		}
		return cursor;
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = openHelper.getReadableDatabase();
		Uri insertUri = null;
		switch (matcher.match(uri)) {
		case MATCH_STUDENT:
			long rowid = db.insert("studentinfo", null, values);
			insertUri = ContentUris.withAppendedId(uri, rowid);
			// 原始URI生成,等價於上面的:long row=db.insert();
			// uri=String path="content://"+authorties+"/studentinfo"+"/"+row;
			break;
		// 返回值是URI,因此要用工具類構造(ContentUris)
		default:
			break;
		}
		return insertUri;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {

		SQLiteDatabase db = openHelper.getReadableDatabase();
		int row = 0;
		switch (matcher.match(uri)) {
		case MATCH_STUDENT:
			// 返回的是影響行數
			row = db.delete("studentinfo", selection, selectionArgs);
			break;

		default:
			break;
		}
		return row;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = openHelper.getReadableDatabase();
		int row = 0;
		switch (matcher.match(uri)) {
		case MATCH_STUDENT:
			// 返回的是影響行數
			db.update("studentinfo", values, selection, selectionArgs);
			break;

		default:
			break;
		}
		return row;
	}

}


//繼承SQLiteOpenHelper的數據庫類
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class MySqliteOpenHelper extends SQLiteOpenHelper {
	// super(context, name, factory, version),要重寫構造方法,父類參數意義
	// context上下文;name:dbName,數據庫名;factory:遊標工廠;version版本號,能夠本身設置
	// 咱們能夠本身重寫,讓它傳入的參數變少,只用傳入上下文

	// 定義一些靜態參數,讓它傳進的參數變少
	private static final String DBNAME = "student2.db";
	// 數據庫會在第一次升級軟件時建立,存放地址:data/data/項目.包名/datebase()
	private static final int VERSION = 1;// 版本能夠本身取

	public MySqliteOpenHelper(Context context) {
		super(context, DBNAME, null, VERSION);
		/*
		 * public MySqliteOpenHelper(Context context, String name, CursorFactory
		 * factory, int version) { super(context, name, factory, version); }
		 */
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// 建立數據庫表,首次升級時調用,初始化一些數據
		String sql = "create table studentinfo "
				+ " (sid integer primary key autoincrement not null,"
				+ " sname varchar(30) not null," + " sex varchar(2) not null,"
				+ " score integer not null)";
		db.execSQL(sql);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// 大於舊版本時,就升級
		if (newVersion > oldVersion) {
			db.execSQL("drop table if exists studentinfo ");
			// 實際操做是先備份數據,再進行刪除升級
		}
	}

}

//清單文件配置
 <!-- provider配置提供給其餘應用跟配置activity差很少,exported="true"true表明給外面調用 -->
        <provider
            android:name="com.example.providercustomUtils.MyContentProvider"
            android:authorities="com.example.providercustomUtils.mycontentprovider"
            android:exported="true" >
        </provider>

//如下是我新建一個項目進行跨應用的測試類

//用來測試自定義ContentProvider類,即跨應用的使用測試(測試的自定義項目名稱是:AndDay16ContentProviderCustom)
public class StudnetProviderTest extends AndroidTestCase {
	// scheme://authority/path
	// authority爲com.example.providercustomUtils.mycontentprovider
	// 要記得你在另一個項目應用的配置的authorities,不能有錯,後面加上路徑、表名等構成Uri
	private String student_uri = "content://com.example.providercustomUtils.mycontentprovider/studentinfo";
	// student_name訪問文本,被操做的應用那裏要寫一個匹配器 ,/*這個是文本標誌
	private String student_name = "content://com.example.providercustomUtils.mycontentprovider/studentinfo/小";// 就想訪問數據庫字段,模糊查詢
	// student_score訪問的是數字,被操做的應用那裏要寫一個匹配器,/#個是數字的標誌
	private String student_score = "content://com.example.providercustomUtils.mycontentprovider/studentinfo_id/90";
	private ContentResolver resolver;
	private Cursor cursor;

	public void queryTest() {
		resolver = getContext().getContentResolver();
		cursor = resolver.query(Uri.parse(student_score), new String[] { "sid",
				"sname", "sex", "score" }, null, null, null);
		while (cursor.moveToNext()) {
			String sname = cursor.getString(cursor.getColumnIndex("sname"));
			String sex = cursor.getString(cursor.getColumnIndex("sex"));
			String score = cursor.getString(cursor.getColumnIndex("score"));
			Log.i("MainActivity", sname + "-" + sex + "-" + score);
			// String sname = cursor.getString(1);
			// String sex = cursor.getString(2);
			// String score = cursor.getString(3);
		}
		cursor.close();
	}

	public void addTest() {
		resolver = getContext().getContentResolver();
		ContentValues values = new ContentValues();
		values.put("sname", "小小");
		values.put("sex", "女");
		values.put("score", 98);
		Uri insertUri = resolver.insert(Uri.parse(student_uri), values);
		Log.i("MainActivity", "row id" + ContentUris.parseId(insertUri));// 系統帶的ContentUris.parseId,把uri放進去能夠返回一個插入後的id
	}

}
//測試時在Mianifest.xml功能文件引入測試單元
 <!-- 引入Android單元測試框架  <application>外面加入-->
    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.example.andday16providercustomtest" >
    </instrumentation>
    <!-- 單元測試的依賴包 在 <application 的裏面加入-->
        <uses-library android:name="android.test.runner" />
相關文章
相關標籤/搜索