ContentProvider使用

概述

今天来看看ContentProvider的使用。

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String TAG = "DatabaseHelper";
    //数据库名称
    private static final String DATABASE_NAME = "person.db";
    //数据库版本
    private static final int DATABASE_VERSION = 1;
    //表名称
    static final String TABLE_STUDENT = "student";
    static final String TABLE_TEACHER = "teacher";
    //创建表结构的语句,注意primary key必须是integer类型的
    private static final String SQL_CREATE_TABLE_STUDENT = "create table " + TABLE_STUDENT + "(" +
            BaseColumns._ID + " integer primary key autoincrement,name varchar(20)" + ");";
    private static final String SQL_CREATE_TABLE_TEACHER = "create table " + TABLE_TEACHER + "(" +
            BaseColumns._ID + " integer primary key autoincrement,name varchar(20)" + ");";

    DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    //第一次创建数据库的时候回调该方法
    //当使用getReadableDatabase()方法获取数据库实例的时候, 如果数据库不存在, 就会调用这个方法;
    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d(TAG, "onCreate: SQL_CREATE_TABLE_STUDENT" + SQL_CREATE_TABLE_STUDENT);
        db.execSQL(SQL_CREATE_TABLE_STUDENT);
        db.execSQL(SQL_CREATE_TABLE_TEACHER);
    }

    //版本号改变时会触发此方法
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}


public class StudentContentProvider extends ContentProvider {
    //ContentProvider唯一标识符,一般是ContentProvier的全类名,要和清单文件中的保持一致
    public static final String AUTHORITY = "com.example.app.StudentContentProvider";
    //路径部分,一般代表数据的集合,一般用表的名字
    public static final String STUDENT = "student";
    public static final String TEACHER = "teacher";
    //代表特定的记录,如果没有指定,返回全部数据
    public static final int MATCH_STUDENT = 1;
    public static final int MATCH_TEACHER = 2;
    private Uri CONTENT_URI_STUDENT = Uri.parse("content://" + AUTHORITY + "/" + STUDENT);
    private Uri CONTENT_URI_TEACHER = Uri.parse("content://" + AUTHORITY + "/" + TEACHER);
    //访问多条记录
    public static final String CONTENT_STUDENT_TYPE = "vnd.android.cursor.dir/student";
    //访问单个记录
    public static final String CONTENT_TEACHER_TYPE = "vnd.android.cursor.item/teacher";
    private static UriMatcher uriMatcher;

    static {
        //完整的匹配路径为content://com.example.app.StudentContentProvider/student/1
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        //表示匹配com.example.app.StudentContentProvider/student,如果匹配成功,返回1
        uriMatcher.addURI(AUTHORITY, STUDENT, MATCH_STUDENT);
        uriMatcher.addURI(AUTHORITY, TEACHER, MATCH_TEACHER);
    }

    private DatabaseHelper mDataBaseHelper;

    @Override
    public boolean onCreate() {
        mDataBaseHelper = new DatabaseHelper(getContext());
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        SQLiteDatabase database = mDataBaseHelper.getReadableDatabase();
        switch (uriMatcher.match(uri)) {
            case MATCH_STUDENT:
                queryBuilder.setTables(DatabaseHelper.TABLE_STUDENT);
                break;
            case MATCH_TEACHER:
                queryBuilder.setTables(DatabaseHelper.TABLE_TEACHER);
                break;
        }
        return queryBuilder.query(database, projection, selection, selectionArgs, null, null, null);
    }

    /**
     *  在query方法中返回Cursor的时候,系统要对Cursor进行分析,进而得出结论,知道该Cursor是多条还是一条记录,
     *  如果我们按照谷歌的建议,手动返回了一个能识别的MIME类型,那么系统就不用自己分析,相当于提高了一点点性能
     */
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch (uriMatcher.match(uri)) {
            case MATCH_STUDENT:
                return CONTENT_STUDENT_TYPE;
            case MATCH_TEACHER:
                return CONTENT_TEACHER_TYPE;
        }
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        SQLiteDatabase database = mDataBaseHelper.getReadableDatabase();
        switch (uriMatcher.match(uri)) {
            case MATCH_STUDENT: {
                long rowId = database.insert(DatabaseHelper.TABLE_STUDENT, null, values);
                if (rowId > 0) {
                    return ContentUris.withAppendedId(CONTENT_URI_STUDENT, rowId);
                }
                break;
            }
            case MATCH_TEACHER:
                long rowId = database.insert(DatabaseHelper.TABLE_TEACHER, null, values);
                if (rowId > 0) {
                    return ContentUris.withAppendedId(CONTENT_URI_TEACHER, rowId);
                }
                break;
        }
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        SQLiteDatabase database = mDataBaseHelper.getWritableDatabase();
        int count = 0;
        switch (uriMatcher.match(uri)) {
            case MATCH_STUDENT:
                count = database.delete(DatabaseHelper.TABLE_STUDENT, selection, selectionArgs);
                break;
            case MATCH_TEACHER:
                count = database.delete(DatabaseHelper.TABLE_STUDENT, selection, selectionArgs);
                break;
        }
        return count;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        SQLiteDatabase database = mDataBaseHelper.getWritableDatabase();
        int count = 0;
        switch (uriMatcher.match(uri)) {
            case MATCH_STUDENT:
                count = database.update(DatabaseHelper.TABLE_STUDENT, values, selection, selectionArgs);
                break;
            case MATCH_TEACHER:
                count = database.update(DatabaseHelper.TABLE_STUDENT, values, selection, selectionArgs);
                break;
        }
        if (getContext() != null) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return count;
    }
}

清单文件配置



外部调用

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    //注意:这里的Uri不能指定特定记录
    public static final Uri URI_STUDENT = Uri.parse("content://com.example.app.StudentContentProvider/student");
    public static final Uri URI_TEACHER = Uri.parse("content://com.example.app.StudentContentProvider/teacher");
    private ContentResolver contentResolver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        contentResolver = getContentResolver();
        contentResolver.registerContentObserver(URI_STUDENT, false, new ContentObserver(new Handler()) {
            @Override
            public void onChange(boolean selfChange, Uri uri) {
                super.onChange(selfChange, uri);
            }
        });
    }

    public void insert(View view) {
        ContentValues values = new ContentValues();
        values.put("name", "张三");
        Uri uri = contentResolver.insert(URI_STUDENT, values);
        Log.d(TAG, "insert: " + uri);
    }

    public void delete(View view) {
        String where = "_id=2";
        contentResolver.delete(URI_STUDENT, where, null);
    }

    public void update(View view) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "李四");
        contentResolver.update(URI_STUDENT, contentValues, "_id=1", null);
    }

    public void query(View view) {
        Cursor cursor = contentResolver.query(URI_STUDENT, null, null, null, null);
        if (cursor != null && cursor.getCount() > 0) {
            while (!cursor.moveToNext()) {
                int id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
                String name = cursor.getString(cursor.getColumnIndex("name"));
                Log.d(TAG, "query: " + id + "--" + name);
            }
            cursor.close();
        }
    }
}


其他问题

如果我们想在其他应用中访问这个ContentProvider,则ContentProvider在清单文件中配置时exported属性必须为true,那么如果我们设置为了true,其他应用都可以访问,岂不是有了安全隐患,这时候可以通过增加权限,下面看怎么做

在ContentProvider所在应用的清单文件中使用android:permission配置权限

 

然后在和application相同节点使用permission标签定义一个权限

  

其中protectionLevel指定权限的级别,具体区别可以看下面的连接

android自定义permission android:protectionLevel说明


这样,其他应用要是想访问我们的ContentProvider,则必须声明一个权限,如下



你可能感兴趣的:(ContentProvider使用)