访问Content Provider数据时出现问题

时间:2018-06-01 08:51:41

标签: android android-contentprovider

在App中创建自定义内容提供商: MProvider ,如下所示:

内容提供商类: BirthProvider

public class BirthProvider extends ContentProvider {
//Content Provider Details
static final String PROVIDER_NAME = "com.mprovider.BirthdayDude";
static final String URL = "content://" + PROVIDER_NAME + "/friends";
static final Uri CONTENT_URI = Uri.parse(URL);

// fields for the database
static final String ID = "id";
static final String NAME = "name";
static final String BIRTHDAY = "birthday";

// integer values used in content URI
static final int FRIENDS = 1;
static final int FRIENDS_ID = 2;
// maps content URI "patterns" to the integer values that were set above
static final UriMatcher uriMatcher;

//database
static final String DATABASE_NAME = "BirthdayReminder";
static final String TABLE_NAME = "birthTable";
static final int DATABASE_VERSION = 1;
static final String CREATE_TABLE =
        " CREATE TABLE " + TABLE_NAME +
                " (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                " name TEXT NOT NULL, " +
                " birthday TEXT NOT NULL);";
// projection map for a query
private static HashMap<String, String> BirthMap;

static {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(PROVIDER_NAME, "friends", FRIENDS);
    uriMatcher.addURI(PROVIDER_NAME, "friends/#", FRIENDS_ID);
}

DBHelper dbHelper;

// database declarations
private SQLiteDatabase database;

@Override
public boolean onCreate() {
    // TODO Auto-generated method stub
    Context context = getContext();
    dbHelper = new DBHelper(context);
    // permissions to be writable
    database = dbHelper.getWritableDatabase();
    if (database == null)
        return false;
    else
        return true;
}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
    // TODO Auto-generated method stub
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    // the TABLE_NAME to query on
    queryBuilder.setTables(TABLE_NAME);

    switch (uriMatcher.match(uri)) {//doubtfull...
        // maps all database column names
        case FRIENDS:
            queryBuilder.setProjectionMap(BirthMap);
            break;
        case FRIENDS_ID:
            queryBuilder.appendWhere(ID + "=" + uri.getLastPathSegment());
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }
    if (sortOrder == null || sortOrder == "") {
        // No sorting-> sort on names by default
        sortOrder = NAME;
    }
    Cursor cursor = queryBuilder.query(database, projection, selection,
            selectionArgs, null, null, sortOrder);
    /**
     * register to watch a content URI for changes
     */
    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;

}

@Nullable
@Override
public String getType(@NonNull Uri uri) {
    // TODO Auto-generated method stub
    switch (uriMatcher.match(uri)) {
        // Get all friend-birthday records
        case FRIENDS:
            return "vnd.android.cursor.dir/vnd.example.friends";
        // Get a particular friend
        case FRIENDS_ID:
            return "vnd.android.cursor.item/vnd.example.friends";
        default:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
    }

}

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
    // TODO Auto-generated method stub
    long row = database.insert(TABLE_NAME, "", values);
    // If record is added successfully
    if (row > 0) {
        Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
        getContext().getContentResolver().notifyChange(newUri, null);
        return newUri;
    }
    throw new SQLException("Fail to add a new record into " + uri);
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
    // TODO Auto-generated method stub
    int count = 0;
    switch (uriMatcher.match(uri)) {
        case FRIENDS:
            // delete all the records of the table
            count = database.delete(TABLE_NAME, selection, selectionArgs);
            break;
        case FRIENDS_ID:
            String id = uri.getLastPathSegment(); //gets the id
            count = database.delete(TABLE_NAME, ID + " = " + id +
                    (!TextUtils.isEmpty(selection) ? " AND (" +
                            selection + ')' : ""), selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unsupported URI " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return count;
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
    // TODO Auto-generated method stub
    int count = 0;
    switch (uriMatcher.match(uri)) {
        case FRIENDS:
            count = database.update(TABLE_NAME, values, selection, selectionArgs);
            break;
        case FRIENDS_ID:
            count = database.update(TABLE_NAME, values, ID +
                    " = " + uri.getLastPathSegment() +
                    (!TextUtils.isEmpty(selection) ? " AND (" +
                            selection + ')' : ""), selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unsupported URI " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return count;

}


// class that creates and manages the provider's database
private static class DBHelper extends SQLiteOpenHelper {

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        db.execSQL(CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        Log.w(DBHelper.class.getName(),
                "Upgrading database from version " + oldVersion + " to "
                        + newVersion + ". Old data will be destroyed");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }
    }
}

现在,在.java类中:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

public void deleteAllBirthdays(View view) {
    // delete all the records and the table of the database provider
    String URL = "content://com.mprovider.BirthdayDude/friends";
    Uri friends = Uri.parse(URL);
    int count = getContentResolver().delete(
            friends, null, null);
    String countNum = "Total " + count + " records are deleted.";
    Toast.makeText(getBaseContext(),
            countNum, Toast.LENGTH_LONG).show();
}

public void addBirthday(View view) {
    // Add a new birthday record
    ContentValues values = new ContentValues();
    values.put(BirthProvider.NAME,
            ((EditText) findViewById(R.id.name)).getText().toString());
    values.put(BirthProvider.BIRTHDAY,
            ((EditText) findViewById(R.id.birthday)).getText().toString());
    Uri uri = getContentResolver().insert(
            BirthProvider.CONTENT_URI, values);
    Toast.makeText(getBaseContext(),
            "==>" + uri.toString() + " inserted!", Toast.LENGTH_LONG).show();
}

public void showAllBirthdays(View view) {
    // Show all the birthdays sorted by friend's name
    String URL = "content://com.mprovider.BirthdayDude/friends";
    Uri friends = Uri.parse(URL);
    Cursor c = getContentResolver().query(friends, null, null, null, "name");
    String result = "Results:";
    if (!c.moveToFirst()) {
        Toast.makeText(this, result + " no content yet!", Toast.LENGTH_LONG).show();
    } else {
        do {
            result = result + "\n" + c.getString(c.getColumnIndex(BirthProvider.NAME)) +
                    " with id " + c.getString(c.getColumnIndex(BirthProvider.ID)) +
                    " has birthday: " + c.getString(c.getColumnIndex(BirthProvider.BIRTHDAY));
        } while (c.moveToNext());
        Toast.makeText(this, result, Toast.LENGTH_LONG).show();
    }
}
}

这里是xml文件,从中调用java文件中的所有三个方法。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
tools:context=".MainActivity" >

<EditText
    android:id="@+id/name"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:hint="@string/name" />

<EditText
    android:id="@+id/birthday"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/name"
    android:layout_below="@+id/name"
    android:ems="10"
    android:hint="@string/birthday" />

<Button
    android:id="@+id/btnAdd"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:onClick="addBirthday"
    android:layout_alignLeft="@+id/birthday"
    android:layout_below="@+id/birthday"
    android:layout_marginTop="30dp"
    android:text="@string/add" />

<Button
    android:id="@+id/btnShow"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/btnAdd"
    android:layout_below="@+id/btnAdd"
    android:layout_marginTop="20dp"
    android:onClick="showAllBirthdays"
    android:text="@string/show" />

<Button
    android:id="@+id/btnDelete"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/btnShow"
    android:layout_alignLeft="@+id/btnShow"
    android:layout_marginTop="20dp"
    android:onClick="deleteAllBirthdays"
    android:text="@string/delete" />

最后,清单中的提供程序的Declation如下:

Permissions:

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
    <uses-permission android:name="android.permission.READ_CALL_LOG"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_CALL_LOG"></uses-permission>

提供者:

<permission  android:name="com.mprovider.BirthdayDude.READ_DATABASE" android:protectionLevel="normal"/>

    <provider android:authorities="com.mprovider.BirthdayDude"
        android:enabled="true"
        android:exported="true"
        android:name="com.mprovider.BirthProvider"
        android:protectionLevel="signature"
        android:readPermission="com.mprovider.BirthdayDude.READ_DATABASE"/>

==&GT;现在,我正在尝试从上面的应用程序获取数据到我的第二个应用程序,如下所示:

App:AccessContents 这是我的java文件:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    showAllBirthdays();
}

public void showAllBirthdays() {

    // Show all the birthdays sorted by friend's name
    String URL = "content://com.mprovider.BirthdayDude/friends";
    Uri friends = Uri.parse(URL);

    ContentProviderClient yourCR = getContentResolver().acquireContentProviderClient(friends);

    Cursor c = getContentResolver().query(friends, null, null, null, "name");
    String result = "Results:";
    if (!c.moveToFirst()) {
        Toast.makeText(this, result + " no content yet!", Toast.LENGTH_LONG).show();
    } else {
        do {
            result = result + "\n" + c.getString(c.getColumnIndex("name")) +
                    " with id " + c.getString(c.getColumnIndex("id")) +
                    " has birthday: " + c.getString(c.getColumnIndex("birthday"));
        } while (c.moveToNext());
        Toast.makeText(this, result, Toast.LENGTH_LONG).show();
    }
}
}

但是,问题是光标内部没有数据。 可能是什么问题?

,错误是:

Caused by: java.lang.SecurityException: Permission Denial: reading com.mprovider.BirthProvider uri content://com.mprovider.BirthdayDude/friends from pid=22395, uid=10118 requires com.mprovider.BirthdayDude.READ_DATABASE, or grantUriPermission() 

感谢。

0 个答案:

没有答案