ContentProvider одной базы данных не позволяет мне получить доступ к данным в другой базе данных в том же приложении для Android - PullRequest
0 голосов
/ 16 сентября 2018

Я делаю приложение электронной коммерции для пекарни (личный проект, чтобы познакомиться с Android).

Я создал две базы данных, одну для хранения данных клиентов для регистрации и другую базу данных для хранения всехтовары, которые в настоящее время есть в наличии, которые можно заказать из списка, где каждый товар содержит кнопку «добавить в корзину».

Я использовал контент-провайдер для первой базы данных, т.е. customerRegistry.db.Когда я пытаюсь отобразить список доступных элементов, мне нужно получить доступ ко второй базе данных, запросить данные и показать их в виде списка правильно?Но ContentProvider в первой базе данных пытается найти URI элементов и выдает сообщение об ошибке.

Я не хочу, чтобы ContentProvider предназначался для данных клиента для поиска URI элементов,очевидно, он не найдет ни одного.Как это предотвратить?

Этот проект является расширением проекта курса Udacity, который я завершил несколько месяцев назад.

Вот код 1-й базы данных, используемой для хранения данных клиентов

Внутри нового пакета я создал следующие классы.

public final class customerContract {

public static final String CONTENT_AUTHORITY = "com.example.dell.nammabakery";

public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

public static final String PATH_DETAILS = "details";

private customerContract() {

}

public static final class customerDataEntry implements BaseColumns {

    public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_DETAILS);

    public static final String CONTENT_LIST_TYPE =
            ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_DETAILS;

    public static final String CONTENT_ITEM_TYPE =
            ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_DETAILS;

    /**
     * Name of database table for customer registry
     */
    public final static String TABLE_NAME = "customerRegistry";

    /**
     * Unique ID number for the item (only for use in the database table).
     * <p>
     * Type: INTEGER
     */

    public final static String _ID = BaseColumns._ID;

    public final static String COLUMN_CUSTOMER_NAME = "name";

    public final static String COLUMN_CUSTOMER_USERNAME = "username";

    public final static String COLUMN_CUSTOMER_PASSWORD = "password";

    public final static String COLUMN_CUSTOMER_EMAIL = "email";

    public final static String COLUMN_CUSTOMER_ADDRESS = "address";

    public final static String COLUMN_PHONE_NUMBER = "phoneNumber";

}
}

Класс, расширяющий SQLiteOpenHelper

public class customerDbHelper extends SQLiteOpenHelper {

public static final String LOG_TAG = customerDbHelper.class.getSimpleName();

/**
 * Name of the database file
 */
private static final String DATABASE_NAME = "customerRegistory.db";

/**
 * Database version. If you change the database schema, you must increment the database version.
 */
private static final int DATABASE_VERSION = 1;

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

@Override
public void onCreate(SQLiteDatabase db) {
    // Create a String that contains the SQL statement to create the pets table
    String SQL_CREATE_ITEMS_TABLE = "CREATE TABLE " + customerDataEntry.TABLE_NAME + " ("
            + customerDataEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
            + customerDataEntry.COLUMN_CUSTOMER_NAME + " TEXT NOT NULL, "
            + customerDataEntry.COLUMN_CUSTOMER_USERNAME + " TEXT NOT NULL, "
            + customerDataEntry.COLUMN_CUSTOMER_PASSWORD + " TEXT NOT NULL, "
            + customerDataEntry.COLUMN_CUSTOMER_EMAIL + " TEXT NOT NULL, "
            + customerDataEntry.COLUMN_CUSTOMER_ADDRESS + " TEXT NOT NULL, "
            + customerDataEntry.COLUMN_PHONE_NUMBER + " LONG NOT NULL);";

    // Execute the SQL statement
    db.execSQL(SQL_CREATE_ITEMS_TABLE);
}

/**
 * This is called when the database needs to be upgraded.
 */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // The database is still at version 1, so there's nothing to do be done here.
}

Класс, расширяющий ContentProvider

public class customerProvider extends ContentProvider {

public static final String LOG_TAG = customerProvider.class.getSimpleName();

/**
 * URI matcher code for the content URI for the customerRegistry table
 */
private static final int CUSTOMERS = 100;

/**
 * URI matcher code for the content URI for a single customer in the registry table
 */
private static final int CUSTOMER_ID = 101;

private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {

    sUriMatcher.addURI(customerContract.CONTENT_AUTHORITY, customerContract.PATH_DETAILS, CUSTOMERS);

    sUriMatcher.addURI(customerContract.CONTENT_AUTHORITY, customerContract.PATH_DETAILS + "/#", CUSTOMER_ID);
}

/**
 * Database helper object
 */
private customerDbHelper mDbHelper;

@Override
public boolean onCreate() {
    mDbHelper = new customerDbHelper(getContext());
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                    String sortOrder) {
    // Get readable database
    SQLiteDatabase database = mDbHelper.getReadableDatabase();

    // This cursor will hold the result of the query
    Cursor cursor;

    // Figure out if the URI matcher can match the URI to a specific code
    int match = sUriMatcher.match(uri);
    switch (match) {
        case CUSTOMERS:

            cursor = database.query(customerDataEntry.TABLE_NAME, projection, selection, selectionArgs,
                    null, null, sortOrder);
            break;
        case CUSTOMER_ID:

            selection = customerDataEntry._ID + "=?";
            selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};

            cursor = database.query(customerDataEntry.TABLE_NAME, projection, selection, selectionArgs,
                    null, null, sortOrder);
            break;
        default:
            throw new IllegalArgumentException("Cannot query unknown URI " + uri);
    }

    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    // Return the cursor
    return cursor;
}

@Override
public Uri insert(Uri uri, ContentValues contentValues) {
    final int match = sUriMatcher.match(uri);
    switch (match) {

        case CUSTOMERS:
            return insertItem(uri, contentValues);

        default:
            throw new IllegalArgumentException("Insertion is not supported for " + uri);
    }
}

private Uri insertItem(Uri uri, ContentValues values) {

    // Check that the name is not null
    String name = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_NAME);
    if (name == null) {
        throw new IllegalArgumentException("Customer requires a name");
    }

    String username = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_USERNAME);
    if(username == null) {
        throw new IllegalArgumentException("Customer requires a username");
    }

    String password = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_PASSWORD);
    if(password == null) {
        throw new IllegalArgumentException("password is required");
    }

    String email = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_EMAIL);
    if (email == null) {
        throw new IllegalArgumentException("Customer requires an emailID");
    }

    // Check that the gender is valid
    String address = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_ADDRESS);
    if (address == null) {
        throw new IllegalArgumentException("Customer requires valid address");
    }

    // If the weight is provided, check that it's greater than or equal to 0 kg
    int phoneNumber  = values.getAsInteger(customerDataEntry.COLUMN_PHONE_NUMBER);
    if (String.valueOf(phoneNumber).length() != 10) {
        throw new IllegalArgumentException("Customer requires a valid phone number");
    }

    // Get writeable database
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Insert the new pet with the given values
    long id = database.insert(customerDataEntry.TABLE_NAME, null, values);
    // If the ID is -1, then the insertion failed. Log an error and return null.
    if (id == -1) {

        Log.e(LOG_TAG, "Failed to insert row for " + uri);
        return null;
    }

    // Notify all listeners that the data has changed for the pet content URI
    getContext().getContentResolver().notifyChange(uri, null);

    // Return the new URI with the ID (of the newly inserted row) appended at the end
    return ContentUris.withAppendedId(uri, id);
}

@Override
public int update(Uri uri, ContentValues contentValues, String selection,
                  String[] selectionArgs) {
    final int match = sUriMatcher.match(uri);
    switch (match) {
        case CUSTOMERS:
            return updateItem(uri, contentValues, selection, selectionArgs);
        case CUSTOMER_ID:
            // For the PET_ID code, extract out the ID from the URI,
            // so we know which row to update. Selection will be "_id=?" and selection
            // arguments will be a String array containing the actual ID.
            selection = customerDataEntry._ID + "=?";
            selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
            return updateItem(uri, contentValues, selection, selectionArgs);
        default:
            throw new IllegalArgumentException("Update is not supported for " + uri);
    }
}

private int updateItem(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    // If the {@link ItemEntry#COLUMN_ITEM_NAME} key is present,
    // check that the name value is not null.
    if (values.containsKey(customerDataEntry.COLUMN_CUSTOMER_NAME)) {
        String name = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_NAME);
        if (name == null) {
            throw new IllegalArgumentException("Customer requires a name");
        }
    }

    if(values.containsKey(customerDataEntry.COLUMN_CUSTOMER_USERNAME)) {
        String username = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_USERNAME);
        if (username == null) {
            throw new IllegalArgumentException("Customer requires a username");
        }
    }

    if(values.containsKey(customerDataEntry.COLUMN_CUSTOMER_PASSWORD)) {
        String password = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_USERNAME);
        if(password == null) {
            throw new IllegalArgumentException("Password is required");
        }
    }

    if (values.containsKey(customerDataEntry.COLUMN_CUSTOMER_EMAIL)) {
        String email = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_EMAIL);
        if (email == null) {
            throw new IllegalArgumentException("Customer requires a valid email");
        }
    }

    // check that the gender value is valid.
    if (values.containsKey(customerDataEntry.COLUMN_CUSTOMER_ADDRESS)) {
        String address = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_ADDRESS);
        if (address == null) {
            throw new IllegalArgumentException("Customer requires valid address");
        }
    }

    // check that the weight value is valid.
    if (values.containsKey(customerDataEntry.COLUMN_PHONE_NUMBER)) {
        // Check that the weight is greater than or equal to 0 kg
        Integer phoneNumber = values.getAsInteger(customerDataEntry.COLUMN_PHONE_NUMBER);
        if (phoneNumber == null || String.valueOf(phoneNumber).length() < 10) {
            throw new IllegalArgumentException("Customer requires a valid phone number");
        }
    }

    // If there are no values to update, then don't try to update the database
    if (values.size() == 0) {
        return 0;
    }

    // Otherwise, get writeable database to update the data
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Perform the update on the database and get the number of rows affected
    int rowsUpdated = database.update(customerDataEntry.TABLE_NAME, values, selection, selectionArgs);

    // If 1 or more rows were updated, then notify all listeners that the data at the
    // given URI has changed

    if (rowsUpdated != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }

    // Return the number of rows updated
    return rowsUpdated;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    // Get writeable database
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Track the number of rows that were deleted
    int rowsDeleted;

    final int match = sUriMatcher.match(uri);
    switch (match) {
        case CUSTOMERS:
            // Delete all rows that match the selection and selection args
            rowsDeleted = database.delete(customerDataEntry.TABLE_NAME, selection, selectionArgs);
            break;
        case CUSTOMER_ID:
            // Delete a single row given by the ID in the URI
            selection = customerDataEntry._ID + "=?";
            selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
            rowsDeleted = database.delete(customerDataEntry.TABLE_NAME, selection, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Deletion is not supported for " + uri);
    }

    // If 1 or more rows were deleted, then notify all listeners that the data at the
    // given URI has changed
    if (rowsDeleted != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }

    // Return the number of rows deleted
    return rowsDeleted;
}

@Override
public String getType(Uri uri) {
    final int match = sUriMatcher.match(uri);
    switch (match) {
        case CUSTOMERS:
            return customerDataEntry.CONTENT_LIST_TYPE;
        case CUSTOMER_ID:
            return customerDataEntry.CONTENT_ITEM_TYPE;
        default:
            throw new IllegalStateException("Unknown URI " + uri + " with match " + match);
    }
}
}

Я создал новый пакет для базы данных товаров, который похож на базу данных customerRegistry.

Во фрагментах я пытался извлечь данные из базы данных элементов и отобразить их в виде списка следующим образом

public class BreadFragment extends Fragment {

private ItemDbHelper dbHelper;
private Context context;

public BreadFragment() {
    // Required empty public constructor
}

@Override
@TargetApi(16)
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.product_list, container, true);
    dbHelper = new ItemDbHelper(getContext());
    SQLiteDatabase db = dbHelper.getReadableDatabase();

    String[] projection = {
            _ID,
            itemDataEntry.COLUMN_ITEM_NAME,
            itemDataEntry.COLUMN_ITEM_DESCRIPTION,
            itemDataEntry.COLUMN_ITEM_IMAGE,
            itemDataEntry.COLUMN_ITEM_PRICE,
    };

    final ArrayList<Product> products = new ArrayList<Product>();

    Cursor cursor = db.query(itemDataEntry.TABLE_NAME, projection, "_ID = 1",null, null, null ,null);
    products.add(new Product(cursor.getString(1), cursor.getString(2), getImage(cursor.getBlob(3)), cursor.getString(4)));

    Cursor cursor1 = db.query(itemDataEntry.TABLE_NAME, projection, "_ID = 2",null, null, null ,null);
    products.add(new Product(cursor1.getString(1), cursor1.getString(2), getImage(cursor1.getBlob(3)), cursor1.getString(4)));

    Cursor cursor2 = db.query(itemDataEntry.TABLE_NAME, projection, "_ID = 3",null, null, null ,null);
    products.add(new Product(cursor2.getString(1), cursor2.getString(2), getImage(cursor2.getBlob(3)), cursor2.getString(4)));

    ProductAdapter adapter = new ProductAdapter(getActivity(), products, R.color.category_cookie);

    ListView listView = (ListView) rootView.findViewById(R.id.list);

    listView.setAdapter(adapter);
    cursor.close();
    cursor1.close();
    cursor2.close();

    return rootView;
}

Но я получаю ошибку от customerProvider (который исходит из содержимогопровайдер) вот так

IllegalArgumentException: невозможно запросить неизвестный URI ......

Этот провайдер предназначен только для проверки и / или обмена данными о клиентах, а не с данными об элементах.Как помешать ему найти детали товаров в customerRegistry.db?

...