赞
踩
跨应用数据共享是 ContentProvider 的一个重要功能,它允许应用之间安全地共享数据。为此,我们需要定义清晰的权限和 URI 结构,以确保数据在不同应用之间安全传输。
在 AndroidManifest.xml
中定义权限:
<permission
android:name="com.example.myapp.READ_DATA"
android:protectionLevel="signature" />
<permission
android:name="com.example.myapp.WRITE_DATA"
android:protectionLevel="signature" />
在 AndroidManifest.xml
中定义 ContentProvider,并设置权限:
<provider
android:name=".MyContentProvider"
android:authorities="com.example.myapp.provider"
android:exported="true"
android:readPermission="com.example.myapp.READ_DATA"
android:writePermission="com.example.myapp.WRITE_DATA" />
实现 ContentProvider 并处理权限:
public class MyContentProvider extends ContentProvider { private static final String AUTHORITY = "com.example.myapp.provider"; private static final String BASE_PATH = "data"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH); private static final int DATA = 1; private static final int DATA_ID = 2; private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { uriMatcher.addURI(AUTHORITY, BASE_PATH, DATA); uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", DATA_ID); } private SQLiteDatabase database; @Override public boolean onCreate() { DatabaseHelper dbHelper = new DatabaseHelper(getContext()); database = dbHelper.getWritableDatabase(); return true; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { if (getContext().checkCallingOrSelfPermission("com.example.myapp.READ_DATA") != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Permission denied"); } switch (uriMatcher.match(uri)) { case DATA: return database.query(DatabaseHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); case DATA_ID: selection = DatabaseHelper.COLUMN_ID + "=?"; selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))}; return database.query(DatabaseHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unknown URI: " + uri); } } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { if (getContext().checkCallingOrSelfPermission("com.example.myapp.WRITE_DATA") != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Permission denied"); } long id = database.insert(DatabaseHelper.TABLE_NAME, null, values); getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(CONTENT_URI, id); } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { if (getContext().checkCallingOrSelfPermission("com.example.myapp.WRITE_DATA") != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Permission denied"); } int rowsDeleted; switch (uriMatcher.match(uri)) { case DATA: rowsDeleted = database.delete(DatabaseHelper.TABLE_NAME, selection, selectionArgs); break; case DATA_ID: selection = DatabaseHelper.COLUMN_ID + "=?"; selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))}; rowsDeleted = database.delete(DatabaseHelper.TABLE_NAME, selection, selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsDeleted; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { if (getContext().checkCallingOrSelfPermission("com.example.myapp.WRITE_DATA") != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Permission denied"); } int rowsUpdated; switch (uriMatcher.match(uri)) { case DATA: rowsUpdated = database.update(DatabaseHelper.TABLE_NAME, values, selection, selectionArgs); break; case DATA_ID: selection = DatabaseHelper.COLUMN_ID + "=?"; selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))}; rowsUpdated = database.update(DatabaseHelper.TABLE_NAME, values, selection, selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsUpdated; } @Nullable @Override public String getType(@NonNull Uri uri) { switch (uriMatcher.match(uri)) { case DATA: return "vnd.android.cursor.dir/vnd.com.example.myapp.provider.data"; case DATA_ID: return "vnd.android.cursor.item/vnd.com.example.myapp.provider.data"; default: throw new IllegalArgumentException("Unknown URI: " + uri); } } }
假设我们正在开发一个音乐播放器应用,需要管理和共享播放列表。每个播放列表包含多个音乐文件。我们将使用 ContentProvider 来管理播放列表,并确保其他应用也可以访问这些播放列表。
public class DatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "music.db"; private static final int DATABASE_VERSION = 1; public static final String TABLE_PLAYLIST = "playlist"; public static final String COLUMN_ID = "_id"; public static final String COLUMN_NAME = "name"; private static final String DATABASE_CREATE = "create table " + TABLE_PLAYLIST + "(" + COLUMN_ID + " integer primary key autoincrement, " + COLUMN_NAME + " text not null);"; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase database) { database.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_PLAYLIST); onCreate(db); } }
public class PlaylistProvider extends ContentProvider { private static final String AUTHORITY = "com.example.musicplayer.provider"; private static final String BASE_PATH = "playlists"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH); private static final int PLAYLISTS = 1; private static final int PLAYLIST_ID = 2; private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { uriMatcher.addURI(AUTHORITY, BASE_PATH, PLAYLISTS); uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", PLAYLIST_ID); } private SQLiteDatabase database; @Override public boolean onCreate() { DatabaseHelper dbHelper = new DatabaseHelper(getContext()); database = dbHelper.getWritableDatabase(); return true; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { switch (uriMatcher.match(uri)) { case PLAYLISTS: return database.query(DatabaseHelper.TABLE_PLAYLIST, projection, selection, selectionArgs, null, null, sortOrder); case PLAYLIST_ID: selection = DatabaseHelper.COLUMN_ID + "=?"; selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))}; return database.query(DatabaseHelper.TABLE_PLAYLIST, projection, selection, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unknown URI: " + uri); } } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { long id = database.insert(DatabaseHelper.TABLE_PLAYLIST, null, values); getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(CONTENT_URI, id); } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { int rowsDeleted; switch (uriMatcher.match(uri)) { case PLAYLISTS: rowsDeleted = database.delete(DatabaseHelper.TABLE_PLAYLIST, selection, selectionArgs); break; case PLAYLIST_ID: selection = DatabaseHelper.COLUMN_ID + "=?"; selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))}; rowsDeleted = database.delete(DatabaseHelper.TABLE_PLAYLIST, selection, selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsDeleted; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { int rowsUpdated; switch (uriMatcher.match(uri)) { case PLAYLISTS: rowsUpdated = database.update(DatabaseHelper.TABLE_PLAYLIST, values, selection, selectionArgs); break; case PLAYLIST_ID: selection = DatabaseHelper.COLUMN_ID + "=?"; selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))}; rowsUpdated = database.update(DatabaseHelper.TABLE_PLAYLIST, values, selection, selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsUpdated; } @Nullable @Override public String getType(@NonNull Uri uri) { switch (uriMatcher.match(uri)) { case PLAYLISTS: return "vnd.android.cursor.dir/vnd.com.example.musicplayer.provider.playlists"; case PLAYLIST_ID: return "vnd.android.cursor.item/vnd.com.example.musicplayer.provider.playlists"; default: throw new IllegalArgumentException("Unknown URI: " + uri); } } }
通过以上示例,我们展示了 ContentProvider 在跨应用数据共享、动态授权、数据观察和通知等方面的高级应用。通过合理设计 URI 结构、权限管理和数据缓存,可以有效提升 ContentProvider 的性能和安全性。在实际开发中,结合具体需求和场景,灵活运用这些高级技巧和最佳实践,是开发高效、可靠 Android 应用的关键。理解和掌握 ContentProvider 的高级使用方法,可以让开发者在数据管理和共享方面得心应手。
欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。