ContentProvider:尝试使用ContentResolver访问数据时,光标对象为null

时间:2019-01-04 17:36:16

标签: android

我正在尝试使用ContentProvider在我的应用之间共享一些数据。我在第二个应用程序中使用解析器访问数据时遇到问题:查询后游标对象为null。无法弄清楚我在代码中哪里出错了,所以我正在寻求帮助。提供数据的第一个应用程序的代码:

清单中的提供者:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.piotr.planer">

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".BroadcastEvent" />

    <provider
        android:authorities="com.example.piotr.planer.PlansProvider"
        android:name=".PlansProvider"
        android:exported="true"
        android:multiprocess="true" >
    </provider>

</application>

提供程序类:

package com.example.piotr.planer;

public class PlansProvider extends ContentProvider {

// Unique namespace for provider
static final String PROVIDER_NAME = "com.example.piotr.planer.PlansProvider";

static final String URL = "content://" + PROVIDER_NAME + "/cpplans";

static final Uri CONTENT_URL = Uri.parse(URL);

// Defining columns in database
static final String id = "id";
static final String name = "name";
static final String date = "date";

static final int uriCode = 1;

private static HashMap<String, String> values;

// UriMatcher matches our unique Uris with our ContentProviders
static final UriMatcher uriMatcher;

// assigning these unique Uris
static {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(PROVIDER_NAME, "cpplans", uriCode);
}

// Defining database
private SQLiteDatabase sqlDB;
static final String DATABASE_NAME = "myPlans";
static final String TABLE_NAME = "plans";
static final int DATABASE_VERSION = 1;
static final String CREATE_DB_TABLE = "CREATE TABLE " + TABLE_NAME +
        " (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
        " name TEXT NOT NULL, " +
        " date INTEGER);";


@Override
public boolean onCreate() {
    // Creates Database
    DatabaseHelper dbHelper = new DatabaseHelper(getContext());
    sqlDB = dbHelper.getWritableDatabase();

    if (sqlDB != null) {
        return true;
    }
    return false;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(TABLE_NAME);

    switch (uriMatcher.match(uri)) {
        case uriCode:
            queryBuilder.setProjectionMap(values);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);

    }
    Cursor cursor = queryBuilder.query(sqlDB, projection, selection, selectionArgs, null, null, sortOrder);
    cursor.setNotificationUri(getContext().getContentResolver(), uri);

    return cursor;
}

@Override
public String getType(Uri uri) {
    switch (uriMatcher.match(uri)) {
        case uriCode:
            return "vnd.android.cursor.dir/cpplans";
        default:
            throw new IllegalArgumentException("Unsupported URI " + uri);

    }
}


@Override
public Uri insert(Uri uri, ContentValues values) {
    long rowID = sqlDB.insert(TABLE_NAME, null, values);
    if (rowID > 0) {
        Uri _uri = ContentUris.withAppendedId(CONTENT_URL, rowID);
        getContext().getContentResolver().notifyChange(_uri, null);
        return uri;
    } else {
        Toast.makeText(getContext(), "Row insert failed", Toast.LENGTH_SHORT).show();
        return null;
    }
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    int rowsDeleted = 0;
    switch (uriMatcher.match(uri)) {
        case uriCode:
            rowsDeleted = sqlDB.delete(TABLE_NAME, selection, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return rowsDeleted;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    int rowsUpdated = 0;
    switch (uriMatcher.match(uri)) {
        case uriCode:
            rowsUpdated = sqlDB.update(TABLE_NAME, values, selection, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}

private static class DatabaseHelper extends SQLiteOpenHelper {

    DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqlDB) {
        sqlDB.execSQL(CREATE_DB_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqlDB, int oldVersion, int newVersion) {
        sqlDB.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(sqlDB);
    }
 }
}

addPlanToProviderFunction()方法:

private void addPlanToProvider(long timeInMillis, String eventName) {
    ContentValues values = new ContentValues();
    values.put(PlansProvider.name, eventName);
    values.put(PlansProvider.date, timeInMillis);

    Uri uri = mContext.getContentResolver().insert(PlansProvider.CONTENT_URL, values);
}

第二个应用中我要获取数据的类:

package com.example.piotr.zadaniowiec;

public class PlanList extends AppCompatActivity {

static final Uri CONTENT_URL = Uri.parse("content://com.example.piotr.planer.PlansProvider.cpplans");

ContentResolver resolver;
TextView planListTextView;

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

    planListTextView = findViewById(R.id.plan_list_text_view);
    resolver = getContentResolver();
    getPlans();
}

private void getPlans() {
    String[] projection = new String[]{"id", "name", "date"};
    Cursor cursor = resolver.query(CONTENT_URL, projection, null, null, null); 

    String planList = "";
    if (cursor.moveToNext()) {                         // I get an error here
        do {
            String id = cursor.getString(cursor.getColumnIndex("id"));
            String name = cursor.getString(cursor.getColumnIndex("name"));
            long date = cursor.getLong(cursor.getColumnIndex("date"));
            planList = planList + id + name + date + "\n";
        } while (cursor.moveToNext());
    }
    planListTextView.setText(planList);
 }
}

我明白了:

  

“ NullPointerException:尝试在空对象引用上调用接口方法'boolean android.database.Cursor.moveToNext()'。”

感谢任何人的帮助。

1 个答案:

答案 0 :(得分:1)

您的CONTENT_URL格式错误-授权后您需要/,而不是.

static final Uri CONTENT_URL =
    Uri.parse("content://com.example.piotr.planer.PlansProvider/cpplans");

现在,您正在寻找具有com.example.piotr.planer.PlansProvider.cpplans权限的ContentProvider的根路径,该权限不存在,因此为空Cursor。