照例,关于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。同一应用的不同进程不涉及到这个变量的值。