当前位置:   article > 正文

深入分析 Android ContentProvider (八)

深入分析 Android ContentProvider (八)

深入分析 Android ContentProvider (八)

ContentProvider 高级使用及最佳实践案例分析(续)

1. 深入了解跨应用数据共享

跨应用数据共享是 ContentProvider 的一个重要功能,它允许应用之间安全地共享数据。为此,我们需要定义清晰的权限和 URI 结构,以确保数据在不同应用之间安全传输。

示例:跨应用数据共享的完整实现
1. 定义权限

AndroidManifest.xml 中定义权限:

<permission
    android:name="com.example.myapp.READ_DATA"
    android:protectionLevel="signature" />
<permission
    android:name="com.example.myapp.WRITE_DATA"
    android:protectionLevel="signature" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
2. 定义 ContentProvider

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" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
3. ContentProvider 实现

实现 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);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114

2. 实践案例:音乐播放器的播放列表管理

案例概述

假设我们正在开发一个音乐播放器应用,需要管理和共享播放列表。每个播放列表包含多个音乐文件。我们将使用 ContentProvider 来管理播放列表,并确保其他应用也可以访问这些播放列表。

1. 数据库设计
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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
2. ContentProvider 实现
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);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100

3. 总结

通过以上示例,我们展示了 ContentProvider 在跨应用数据共享、动态授权、数据观察和通知等方面的高级应用。通过合理设计 URI 结构、权限管理和数据缓存,可以有效提升 ContentProvider 的性能和安全性。在实际开发中,结合具体需求和场景,灵活运用这些高级技巧和最佳实践,是开发高效、可靠 Android 应用的关键。理解和掌握 ContentProvider 的高级使用方法,可以让开发者在数据管理和共享方面得心应手。

欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/902621
推荐阅读
相关标签
  

闽ICP备14008679号