android - Program is crashing when I call getContentResolver().insert() giving a bad Url error -
full project here program crashing when call getcontentresolver().insert() , dont understand why. im learning sqlite databases in android, task make inventory app store record item, price, quantity, supplier , description. there main activity list view of items , button changes editor activity add items database editoractivity. think not adding _id uri:
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(""); } }
this 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 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 + " 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 not supported " + uri); } } private uri insertitem(uri uri, contentvalues values){ /** todo: verificar se os inputs são validos **/ sqlitedatabase database = mdbhelper.getwritabledatabase(); // insert new pet given values long id = database.insert(inventoryentry.table_name, null, values); // if id -1, insertion failed. log error , return null. if (id == -1) { log.e(log_tag, "failed insert row " + 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 number of rows deleted int rowsdeleted; final int match = surimatcher.match(uri); switch (match) { case inventory: // delete rows match selection , selection args rowsdeleted = database.delete(inventoryentry.table_name, selection, selectionargs); break; case inventory_id: // delete single row given id in 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 not supported " + uri); } if (rowsdeleted != 0) { getcontext().getcontentresolver().notifychange(uri, null); } // return 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 not supported " + 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 number of rows updated return rowsupdated; } }
the inventorycontract:
package com.example.android.inventory.data; import android.content.contentresolver; import android.net.uri; import android.provider.basecolumns; /** * created 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"; } }
and 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 sql statement db.execsql(sql_create_inventory_table); } @override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { } }
error:
07-26 01:54:11.067 15263-15263/com.example.android.inventory e/activitythread: failed find provider info 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 @ android.content.contentresolver.insert(contentresolver.java:1270) @ com.example.android.inventory.editoractivity.saveitem(editoractivity.java:114) @ com.example.android.inventory.editoractivity.onoptionsitemselected(editoractivity.java:149) @ android.app.activity.onmenuitemselected(activity.java:3204) @ android.support.v4.app.fragmentactivity.onmenuitemselected(fragmentactivity.java:360) @ android.support.v7.app.appcompatactivity.onmenuitemselected(appcompatactivity.java:194) @ android.support.v7.view.windowcallbackwrapper.onmenuitemselected(windowcallbackwrapper.java:110) @ android.support.v7.app.appcompatdelegateimplv9.onmenuitemselected(appcompatdelegateimplv9.java:676) @ android.support.v7.view.menu.menubuilder.dispatchmenuitemselected(menubuilder.java:821) @ android.support.v7.view.menu.menuitemimpl.invoke(menuitemimpl.java:158) @ android.support.v7.view.menu.menubuilder.performitemaction(menubuilder.java:968) @ android.support.v7.view.menu.menubuilder.performitemaction(menubuilder.java:958) @ android.support.v7.widget.actionmenuview.invokeitem(actionmenuview.java:623) @ android.support.v7.view.menu.actionmenuitemview.onclick(actionmenuitemview.java:147) @ android.view.view.performclick(view.java:5610) @ android.view.view$performclick.run(view.java:22265) @ android.os.handler.handlecallback(handler.java:751) @ android.os.handler.dispatchmessage(handler.java:95) @ android.os.looper.loop(looper.java:154) @ android.app.activitythread.main(activitythread.java:6077) @ java.lang.reflect.method.invoke(native method) @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:866) @ com.android.internal.os.zygoteinit.main(zygoteinit.java:756)
manifest:
<?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>
Comments
Post a Comment