//繼承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" />