当我调用getContentResolver()。insert()给出错误的Url错误

时间:2017-07-26 01:33:41

标签: android sqlite android-contentprovider android-cursorloader

完整项目here 当我调用getContentResolver()。insert()并且我不明白为什么时,我的程序崩溃了。我正在学习android中的sqlite数据库,所以我的任务是为商店制作一个库存应用程序,我记录项目,价格,数量,供应商和描述。主要活动包含所有项目的列表视图,按钮包含对编辑器活动的更改,其中我将项目添加到数据库,这是EditorActivity。我认为它不是在向Uri添加_id:

  package com.example.android.inventory;

import android.app.LoaderManager;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.example.android.inventory.data.InventoryContract.InventoryEntry;

public class EditorActivity extends AppCompatActivity implements
        LoaderManager.LoaderCallbacks<Cursor> {

    private static final int EXISTING_INVENTORY_LOADER = 0;

    private Uri mCurrentItemUri;

    private EditText mItemName;

    private EditText mItemPrice;

    private EditText mItemQuantity;

    private EditText mItemSupplier;

    private EditText mItemDescription;

    private boolean mItemHasChanged = false;

    private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            mItemHasChanged = true;
            return false;
        }
    };

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

        Intent intent = getIntent();

        mCurrentItemUri = intent.getData();

        if (mCurrentItemUri == null) {
            setTitle(getString(R.string.add_item));
            invalidateOptionsMenu();
        } else {
            setTitle(getString(R.string.update_item));
            getLoaderManager().initLoader(EXISTING_INVENTORY_LOADER, null, this);
        }

        mItemName = (EditText) findViewById(R.id.name_edit_view);
        mItemPrice = (EditText) findViewById(R.id.price_edit_view);
        mItemQuantity = (EditText) findViewById(R.id.quantity_edit_view);
        mItemSupplier = (EditText) findViewById(R.id.supplier_edit_view);
        mItemDescription = (EditText) findViewById(R.id.description_edit_view);

        mItemName.setOnTouchListener(mTouchListener);
        mItemPrice.setOnTouchListener(mTouchListener);
        mItemQuantity.setOnTouchListener(mTouchListener);
        mItemSupplier.setOnTouchListener(mTouchListener);
        mItemDescription.setOnTouchListener(mTouchListener);
    }

    private void saveItem() {

        String nameStr = mItemName.getText().toString().trim();
        String priceStr = mItemPrice.getText().toString().trim();
        String quantityStr = mItemQuantity.getText().toString().trim();
        String supplierStr = mItemSupplier.getText().toString().trim();
        String descriptionStr = mItemDescription.getText().toString().trim();

        if (mCurrentItemUri == null && TextUtils.isEmpty(nameStr) && TextUtils.isEmpty(priceStr) && TextUtils.isEmpty(quantityStr)
                && TextUtils.isEmpty(supplierStr) && TextUtils.isEmpty(descriptionStr)) {
            return;
        }

        ContentValues values = new ContentValues();

        values.put(InventoryEntry.COLUMN_ITEM_NAME, nameStr);

        int price = 0;
        int quantity = 0;

        if (!TextUtils.isEmpty(priceStr))
            price = Integer.parseInt(priceStr);

        if (!TextUtils.isEmpty(quantityStr))
            quantity = Integer.parseInt(quantityStr);

        values.put(InventoryEntry.COLUMN_ITEM_PRICE, price);
        values.put(InventoryEntry.COLUMN_ITEM_QUANTITY, quantity);
        values.put(InventoryEntry.COLUMN_ITEM_SUPPLIER, supplierStr);
        values.put(InventoryEntry.COLUMN_ITEM_DESCRIPTION, descriptionStr);

        if (mCurrentItemUri == null) {

            Uri newUri = getContentResolver().insert(InventoryEntry.CONTENT_URI, values);

            if (newUri == null) {
                Toast.makeText(this, getString(R.string.error_insert_item),
                        Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, R.string.new_item_add,
                        Toast.LENGTH_SHORT).show();
            }
        } else {
            int rowsAffected = getContentResolver().update(mCurrentItemUri, values, null, null);

            if (rowsAffected == 0) {
                Toast.makeText(this, R.string.error_update_item,
                        Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, R.string.update_item_success,
                        Toast.LENGTH_SHORT).show();
            }
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.editor_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

            case R.id.action_save:
                saveItem();
                finish();
                return true;
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(EditorActivity.this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        finish();
        super.onBackPressed();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {

        String[] projection = {
                InventoryEntry._ID,
                InventoryEntry.COLUMN_ITEM_NAME,
                InventoryEntry.COLUMN_ITEM_PRICE,
                InventoryEntry.COLUMN_ITEM_QUANTITY,
                InventoryEntry.COLUMN_ITEM_SUPPLIER,
                InventoryEntry.COLUMN_ITEM_DESCRIPTION};

        return new CursorLoader(this, mCurrentItemUri, projection, null, null, null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

        if (cursor == null || cursor.getCount() < 1) {
            return;
        }

        if (cursor.moveToFirst()) {

            int nameColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_ITEM_NAME);
            int priceColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_ITEM_PRICE);
            int quantityColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_ITEM_QUANTITY);
            int supplierColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_ITEM_SUPPLIER);
            int descriptionColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_ITEM_DESCRIPTION);

            String name = cursor.getString(nameColumnIndex);
            String price = cursor.getString(priceColumnIndex) + getString(R.string.currency_symbol);
            String quantity = cursor.getString(quantityColumnIndex);
            String supplier = cursor.getString(supplierColumnIndex);
            String description = cursor.getString(descriptionColumnIndex);

            mItemName.setText(name);
            mItemPrice.setText(price);
            mItemQuantity.setText(quantity);
            mItemSupplier.setText(supplier);
            mItemDescription.setText(description);

        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

        mItemName.setText("");
        mItemPrice.setText("");
        mItemQuantity.setText("");
        mItemSupplier.setText("");
        mItemDescription.setText("");
    }
}

这是InventoryProvider:

package com.example.android.inventory.data;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import com.example.android.inventory.data.InventoryContract.InventoryEntry;

import static com.example.android.inventory.data.InventoryDbHelper.LOG_TAG;

public class InventoryProvider extends ContentProvider {

    private static final int INVENTORY = 100;
    private static final int INVENTORY_ID = 101;

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

    static {

        sUriMatcher.addURI(InventoryContract.CONTENT_AUTHORITY, InventoryContract.PATH_INVENTORY, INVENTORY);

        sUriMatcher.addURI(InventoryContract.CONTENT_AUTHORITY, InventoryContract.PATH_INVENTORY + "/#", INVENTORY_ID);
    }

    private InventoryDbHelper mDbHelper;

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

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        SQLiteDatabase database = mDbHelper.getReadableDatabase();

        Cursor cursor;

        int match = sUriMatcher.match(uri);

        switch (match) {
            case INVENTORY:

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

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

                cursor = database.query(InventoryEntry.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;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {

        final int match = sUriMatcher.match(uri);
        switch (match) {
            case INVENTORY:
                return InventoryEntry.CONTENT_LIST_TYPE;
            case INVENTORY_ID:
                return InventoryEntry.CONTENT_ITEM_TYPE;
            default:
                throw new IllegalStateException("Unknown URI " + uri + " with match " + match);
        }
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        final int match = sUriMatcher.match(uri);
        switch (match) {
            case INVENTORY:
                return insertItem(uri, contentValues);
            default:
                throw new IllegalArgumentException("Insertion is not supported for " + uri);
        }
    }

    private Uri insertItem(Uri uri, ContentValues values){

        /** TODO: verificar se os inputs são validos **/

        SQLiteDatabase database = mDbHelper.getWritableDatabase();

        // Insert the new pet with the given values
        long id = database.insert(InventoryEntry.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;
        }

        getContext().getContentResolver().notifyChange(uri, null);

        return ContentUris.withAppendedId(uri, id);

    }

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

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

        final int match = sUriMatcher.match(uri);

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

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

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

    @Override
    public int update(Uri uri, ContentValues contentValues, String selection,
                      String[] selectionArgs) {

        final int match = sUriMatcher.match(uri);
        switch (match) {
            case INVENTORY:
                return updateInventory(uri, contentValues, selection, selectionArgs);

            case INVENTORY_ID:
                selection = InventoryEntry._ID + "=?";
                selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
                return updateInventory(uri, contentValues, selection, selectionArgs);

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

    private int updateInventory(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        int rowsUpdated = db.update(InventoryEntry.TABLE_NAME, values, selection, selectionArgs);

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

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

}

InventoryContract:

package com.example.android.inventory.data;

import android.content.ContentResolver;
import android.net.Uri;
import android.provider.BaseColumns;

/**
 * Created by Rodrigo on 23/07/2017.
 */

public class InventoryContract {

    private InventoryContract() {
    }


    public static final String CONTENT_AUTHORITY = "com.example.android.inventory";

    public static final String PATH_INVENTORY = "items";

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


    public static final class InventoryEntry implements BaseColumns {


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

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

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

        public static String TABLE_NAME = "items";

        public final static String _ID = BaseColumns._ID;

        public static String COLUMN_ITEM_NAME = "item";

        public static String COLUMN_ITEM_PRICE = "price";

        public static String COLUMN_ITEM_QUANTITY = "quantity";

        public static String COLUMN_ITEM_SUPPLIER = "supplier";

        public static String COLUMN_ITEM_DESCRIPTION = "description";

        public static String COLUMN_ITEM_IMAGE = "image";


    }

}

和InventoryDbHelper:

package com.example.android.inventory.data;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.example.android.inventory.data.InventoryContract.InventoryEntry;



public class InventoryDbHelper extends SQLiteOpenHelper {

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


    private static final String DATABASE_NAME = "inventory.db";

    private static final int DATABASE_VERSION = 1;

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


    @Override
    public void onCreate(SQLiteDatabase db) {

        String SQL_CREATE_INVENTORY_TABLE = "CREATE TABLE " + InventoryEntry.TABLE_NAME + " ("
                + InventoryEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                + InventoryEntry.COLUMN_ITEM_NAME + " TEXT NOT NULL, "
                + InventoryEntry.COLUMN_ITEM_PRICE + " INTEGER NOT NULL DEFAULT 0,"
                + InventoryEntry.COLUMN_ITEM_QUANTITY + " INTEGER NOT NULL DEFAULT 0, "
                + InventoryEntry.COLUMN_ITEM_SUPPLIER + " TEXT NOT NULL,"
                + InventoryEntry.COLUMN_ITEM_DESCRIPTION + "TEXT);";

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


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

错误:

07-26 01:54:11.067 15263-15263/com.example.android.inventory E/ActivityThread: Failed to find provider info for com.example.android.inventory
07-26 01:54:11.068 15263-15263/com.example.android.inventory D/AndroidRuntime: Shutting down VM
07-26 01:54:11.068 15263-15263/com.example.android.inventory E/AndroidRuntime: FATAL EXCEPTION: main
                                                                               Process: com.example.android.inventory, PID: 15263
                                                                               java.lang.IllegalArgumentException: Unknown URL content://com.example.android.inventory/items
                                                                                   at android.content.ContentResolver.insert(ContentResolver.java:1270)
                                                                                   at com.example.android.inventory.EditorActivity.saveItem(EditorActivity.java:114)
                                                                                   at com.example.android.inventory.EditorActivity.onOptionsItemSelected(EditorActivity.java:149)
                                                                                   at android.app.Activity.onMenuItemSelected(Activity.java:3204)
                                                                                   at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:360)
                                                                                   at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:194)
                                                                                   at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:110)
                                                                                   at android.support.v7.app.AppCompatDelegateImplV9.onMenuItemSelected(AppCompatDelegateImplV9.java:676)
                                                                                   at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:821)
                                                                                   at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
                                                                                   at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:968)
                                                                                   at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
                                                                                   at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:623)
                                                                                   at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:147)
                                                                                   at android.view.View.performClick(View.java:5610)
                                                                                   at android.view.View$PerformClick.run(View.java:22265)
                                                                                   at android.os.Handler.handleCallback(Handler.java:751)
                                                                                   at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                   at android.os.Looper.loop(Looper.java:154)
                                                                                   at android.app.ActivityThread.main(ActivityThread.java:6077)
                                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
                                                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

清单:

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

    <provider
        android:name=".data.InventoryProvider"
        android:authorities="com.example.android.inventory"
        android:exported="false" />

    <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=".InventoryActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".EditorActivity">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".InventoryActivity" />
        </activity>
    </application>

</manifest>

0 个答案:

没有答案