Я делаю приложение электронной коммерции для пекарни (личный проект, чтобы познакомиться с 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?