照例,關於ContentProvider的使用,我們可以參考http://blog.csdn.net/chuyuqing/article/details/39995607這篇文章。
常見的ContentProvider我們常常是對接的數據庫使用,而實際上後邊的存儲類型ContentProvider是不關心的,可以時數據庫,可以是文件。
ContentProvider的主要特徵和利用的集中點:跨進程,而SharedPreference是不能跨進程通信的。
而在我們實際的工程中,有可能一個項目會啓動多個進程,這時就需要我們保存在SharedPreference中的數據可以跨進程通信。那麼我們如何讓SharedPreference也可以實現跨進程呢?
我們就可以考慮在SharedPreference外層封裝一層ContentProvider,這樣子SharedPreference就可以間接的跨進程通信了。
/** * 跨進程讀取SharedPreferences * * 通過SharePersistentUtils工具進行讀和寫SharedPreferencesProvider時,同時要把要操作的文件名傳過來 * <br/>1. 如果調用query()方法,在projection裏添加SharedName * <br/>2. 如果調用update()方法,在ContentValues裏添加SharedName * <br/>3. 如果調用delete()方法,在String[] selectionArgs裏添加SharedName * * * */ public class SharedPreferencesProvider extends ContentProvider{ private static String SHARED_NAME = ""; //跨進程訪問的sharedpreference文件名 private static UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); public static void init(String shareName, String authority){ SharePersistentUtils.init(authority); SHARED_NAME = shareName; sURIMatcher.addURI(authority, Constant.PreferencesCP.TYPE_BOOLEAN, Constant.PreferencesCP.CODE_BOOLEAN); sURIMatcher.addURI(authority, Constant.PreferencesCP.TYPE_INT, Constant.PreferencesCP.CODE_INT); sURIMatcher.addURI(authority, Constant.PreferencesCP.TYPE_LONG, Constant.PreferencesCP.CODE_LONG); sURIMatcher.addURI(authority, Constant.PreferencesCP.TYPE_STRING, Constant.PreferencesCP.CODE_STRING); } @Override public boolean onCreate() { return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // 如果傳入了Shared_Name就使用傳入的SharedPerference的文件名稱,如果沒有傳入,就使用默認的SHARED_NAME String sharedName = SHARED_NAME; if(projection.length >= 3 && !TextUtils.isEmpty(projection[2])) { sharedName = projection[2]; // 注意,已經固定爲第三個元素爲Shared_name了 } SharedPreferences sp = getContext().getSharedPreferences(sharedName, 0); MatrixCursor matrixCursor = new MatrixCursor(new String[] {Constant.PreferencesCP.VALUE}); Object[] itemValues = new Object[1]; try { switch(sURIMatcher.match(uri)){ case Constant.PreferencesCP.CODE_BOOLEAN: boolean boolDefValue = Boolean.parseBoolean(projection[1]); boolean boolValue = sp.getBoolean(projection[0], boolDefValue); if(boolValue){ itemValues[0] = 1; }else{ itemValues[0] = 0; } break; case Constant.PreferencesCP.CODE_INT: int intDefValue = 0; try { intDefValue = Integer.parseInt(projection[1]); } catch (Exception e) { } int intValue = sp.getInt(projection[0], intDefValue); itemValues[0] = intValue; break; case Constant.PreferencesCP.CODE_LONG: long longDefValue = 0; try { longDefValue = Long.parseLong(projection[1]); } catch (Exception e) { } long longValue = sp.getLong(projection[0], longDefValue); itemValues[0] = longValue; break; case Constant.PreferencesCP.CODE_STRING: String stringValue = sp.getString(projection[0], projection[1]); itemValues[0] = stringValue; break; default: return null; } matrixCursor.addRow(itemValues); return matrixCursor; } catch (Exception e) { return null; } } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // 如果傳入了Shared_Name就使用傳入的SharedPerference的文件名稱,如果沒有傳入,就使用默認的SHARED_NAME String sharedName = SHARED_NAME; if(selectionArgs.length >= 2 && !TextUtils.isEmpty(selectionArgs[1])) { sharedName = selectionArgs[1]; // 注意,已經固定爲第三個元素爲Shared_name了 } SharedPreferences sp = getContext().getSharedPreferences(sharedName, 0); Editor editor = sp.edit(); editor.remove(selectionArgs[0]); editor.commit(); return 1; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // 如果傳入了Shared_Name就使用傳入的SharedPerference的文件名稱,如果沒有傳入,就使用默認的SHARED_NAME String sharedName = values.getAsString(Constant.PreferencesCP.SHARED_NAME); // 注意,已經固定爲第三個元素爲Shared_name了 if(TextUtils.isEmpty(sharedName)){ sharedName = SHARED_NAME; } SharedPreferences sp = getContext().getSharedPreferences(sharedName, 0); Editor editor = sp.edit(); String key = values.getAsString(Constant.PreferencesCP.KEY); switch(sURIMatcher.match(uri)){ case Constant.PreferencesCP.CODE_BOOLEAN: editor.putBoolean(key, values.getAsBoolean(Constant.PreferencesCP.VALUE_BOOLEAN)); break; case Constant.PreferencesCP.CODE_INT: editor.putInt(key, values.getAsInteger(Constant.PreferencesCP.VALUE_INT).intValue()); break; case Constant.PreferencesCP.CODE_LONG: editor.putLong(key, values.getAsLong(Constant.PreferencesCP.VALUE_LONG).longValue()); break; case Constant.PreferencesCP.CODE_STRING: editor.putString(key, values.getAsString(Constant.PreferencesCP.VALUE_STRING)); break; } editor.commit(); return 1; } }
另外,Android:exported這個屬性,如果設爲true,其他應用程序就可以通過Content_URI來調用對應的數據,否則其他應用不能使用。詳見:http://blog.csdn.net/watermusicyes/article/details/46460347。同一應用的不同進程不涉及到這個變量的值。