I have a Content Provider that can create one type of database. My database contains 5 columns and one table, and with my program, I want to be able to create a new table with the same columns as my first table. How can I change my Content Provider to do this ? I need to mach some uri, but how can I do this will I am in my program ?
My columns are :
_id, THEME, QUESTION, REPONSE, DIFFICULTE
Here is my Content Provider :
public class CardContentProvider extends ContentProvider {
private StockCard stock;
public static String authority = "com.example.jean.cartememoire.CardContentProvider";
private static String path ="Cartes_table";
public static final String _ID = "_id";
public static final String THEME = "THEME";
public static final String QUESTION = "QUESTION";
public static final String REPONSE = "REPONSE";
public static final String DIFFICULTE = "DIFFICULTE"; //# = un chiffre
public static final String STOCK_TABLE = "Cartes_table";
private static final int ID_STOCK_TABLE = 1;
private static final int ID_THEME = 2;
private static final int ID_QUESTION = 3;
private static final int ID_REPONSE = 4;
private static final int ID_DIFFICULTE = 5;
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
matcher.addURI(authority, STOCK_TABLE, ID_STOCK_TABLE);
matcher.addURI(authority, STOCK_TABLE+"/*", ID_STOCK_TABLE);
}
#Override
public boolean onCreate() {
stock = StockCard.getInstance(getContext());
return true;
}
#Nullable
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = stock.getReadableDatabase();
int code = matcher.match(uri);
long id;
Cursor cursor;
switch (code)
{
case ID_STOCK_TABLE:
cursor = db.query(STOCK_TABLE, projection, selection,
selectionArgs, null, null, sortOrder);
break;
default:
Log.d("Uri provider =", uri.toString());
throw new UnsupportedOperationException("Pas encore implémenté");
}
return cursor;
}
#Nullable
#Override
public String getType(Uri uri) {
return null;
}
#Nullable
#Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = stock.getWritableDatabase();
int code = matcher.match(uri);
long id;
Uri.Builder builder = new Uri.Builder();
switch(code)
{
case ID_STOCK_TABLE:
System.out.println(values.toString());
id = db.insert(STOCK_TABLE, null, values);
builder.appendPath(STOCK_TABLE);
break;
default:
throw new UnsupportedOperationException("Pas encore implémenté");
}
builder.authority(authority);
builder = ContentUris.appendId(builder, id);
return builder.build();
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = stock.getWritableDatabase();
int code = matcher.match(uri);
int i;
switch(code)
{
case ID_STOCK_TABLE:
long id = ContentUris.parseId(uri);
i = db.delete(STOCK_TABLE, "_id=" + id, null);
break;
default:
throw new UnsupportedOperationException("Pas encore implémenté");
}
return 0;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
Thank you guys !
EDIT : I said rows instead of columns...
Related
I wanted to calculate the total price of the products in the cart using SQLite. When I set the price in textview using Settext(), it does not return the sum value. This is the gettotalprice method in DBhelper class.
public int getTotalExpenses()
{
int total = 0;
SQLiteDatabase database = this.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT SUM("+ OrderContract.OrderEntry.COLUMN_PRICE + ") FROM " + OrderContract.OrderEntry.TABLE_NAME, null);
if (cursor.moveToFirst())
{
total = cursor.getInt(4);
}
while (cursor.moveToNext());
return total;
}
OrderProvider class:
package com.example.myapp;
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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class OrderProvider extends ContentProvider {
// this constant is needed in order to define the path of our modification in the table
public static final int ORDER=100;
public DBHelper mhelper;
public static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(OrderContract.CONTENT_AUTHORITY,OrderContract.PATH,ORDER);
}
#Override
public boolean onCreate() {
mhelper = new DBHelper(getContext());
return true;
}
#Override
public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase database = mhelper.getReadableDatabase();
Cursor cursor;
int match = sUriMatcher.match(uri);
switch (match){
case ORDER:
cursor = database.query(OrderContract.OrderEntry.TABLE_NAME, projection, selection, selectionArgs, null,null, sortOrder);
break;
default:
throw new IllegalArgumentException("CANT QUERY");
}
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
int match = sUriMatcher.match(uri);
switch (match) {
case ORDER:
return insertCart(uri, values);
default:
throw new IllegalArgumentException("Cant insert data");
}
}
private Uri insertCart(Uri uri, ContentValues values) {
String name = values.getAsString(OrderContract.OrderEntry.COLUMN_NAME);
if(name == null){
throw new IllegalArgumentException("Name is Required");
}
String quantity = values.getAsString(OrderContract.OrderEntry.COLUMN_QUANTITY);
if(quantity == null){
throw new IllegalArgumentException("Quantity is Required");
}
String price = values.getAsString(OrderContract.OrderEntry.COLUMN_PRICE);
if(price == null){
throw new IllegalArgumentException("Price is Required");
}
//insert values into order
SQLiteDatabase database = mhelper.getWritableDatabase();
long id = database.insert(OrderContract.OrderEntry.TABLE_NAME, null, values);
if(id == 0){
return null;
}
getContext().getContentResolver().notifyChange(uri,null);
return ContentUris.withAppendedId(uri,id);
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//delete data once order is made
int rowsDeleted;
SQLiteDatabase database = mhelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
switch (match) {
case ORDER:
rowsDeleted = database.delete(OrderContract.OrderEntry.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Cannot delete");
}
if (rowsDeleted!=0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
OrderContract class:
public class OrderContract {
public OrderContract() {
}
//content authority requires package name
public static final String CONTENT_AUTHORITY = "com.example.myapp";
public static final Uri BASE_URI = Uri.parse(("content://" +CONTENT_AUTHORITY));
//same as table name
public static final String PATH = "orders" ;
public static abstract class OrderEntry implements BaseColumns{
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_URI,PATH);
public static final String TABLE_NAME = "orders" ;
public static final String _ID = BaseColumns._ID ;
public static final String COLUMN_NAME = "name" ;
public static final String COLUMN_QUANTITY = "quantity" ;
public static final String COLUMN_PRICE = "price" ;
}
}
Cart activity:
sofaname=findViewById(R.id.sofaname);
sofaprice=findViewById(R.id.sofaprice);
sofadesc=findViewById(R.id.sofadesc);
plusquantity = findViewById(R.id.addquantity);
minusquantity = findViewById(R.id.subquantity);
quantitynumber = findViewById(R.id.quantity);
addtocart = findViewById(R.id.addtocart);
ImageSlider imageSlider = findViewById(R.id.sofaslider1);
List<SlideModel> slideModels = new ArrayList<>();
slideModels.add(new SlideModel(R.drawable.card14));
slideModels.add(new SlideModel(R.drawable.card6));
slideModels.add(new SlideModel(R.drawable.card7));
imageSlider.setImageList(slideModels,false);
imageSlider.setClickable(false);
DB = new DBHelper(Sofa1.this);
String Name = DB.getProductNamePrice("SELECT F_Name FROM Furniture WHERE F_Type = 'Sofa';");
String Price = DB.getProductNamePrice("SELECT F_Price FROM Furniture WHERE F_Type = 'Sofa';");
String Desc = DB.getProductNamePrice("SELECT F_Description FROM Furniture WHERE F_Type = 'Sofa';");
sofaname.setText(Name);
sofaprice.setText(Price);
sofadesc.setText(Desc);
plusquantity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(quantity<5){
//sofaprice
int baseprice= Integer.parseInt(sofaprice.getText().toString());
quantity++;
displayquantity();
totalprice = baseprice * quantity;
String setnewprice = (String.valueOf(totalprice));
sofaprice.setText(setnewprice);
}
}
});
minusquantity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int baseprice=0;
String Price = DB.getProductNamePrice("SELECT F_Price FROM Furniture WHERE F_Type = 'Sofa';");
baseprice = Integer.parseInt(Price);
if(quantity>1) {
quantity--;
displayquantity();
totalprice = baseprice * quantity;
String setnewprice = (String.valueOf(totalprice));
sofaprice.setText(setnewprice);
}
}
});
addtocart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent =new Intent(Sofa1.this,Cart.class);
startActivity(intent);
// once this button is clicked we want to save our values in the database and send those values
// right away to summary activity where we display the order info
SaveCart();
totalamount = (TextView) findViewById(R.id.total);
int totalAmount = DB.getTotalExpenses();
totalamount.setText(String.valueOf(totalAmount));
}
});
}
private boolean SaveCart() {
String name = sofaname.getText().toString();
String price = sofaprice.getText().toString();
String quantity = quantitynumber.getText().toString();
ContentValues values = new ContentValues();
values.put(OrderContract.OrderEntry.COLUMN_NAME,name);
values.put(OrderContract.OrderEntry.COLUMN_PRICE,price);
values.put(OrderContract.OrderEntry.COLUMN_QUANTITY,quantity);
if(mcurrentcarturi == null){
Uri newUri = getContentResolver().insert(OrderContract.OrderEntry.CONTENT_URI, values);
if(newUri == null){
Toast.makeText(this, "Failed to add to cart", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "Product added to cart", Toast.LENGTH_SHORT).show();
}
}
hasallrequiredvalues = true;
return hasallrequiredvalues;
}
private void displayquantity() {
quantitynumber.setText(String.valueOf(quantity));
}
#Override
public #NotNull Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {OrderContract.OrderEntry._ID,
OrderContract.OrderEntry.COLUMN_NAME,
OrderContract.OrderEntry.COLUMN_PRICE,
OrderContract.OrderEntry.COLUMN_QUANTITY};
return new CursorLoader(this, mcurrentcarturi, projection, null, null, null);
}
#Override
public void onLoadFinished(#NotNull Loader<Cursor> loader, Cursor cursor) {
if(cursor==null || cursor.getCount() < 1){
return;
}
if(cursor.moveToFirst()){
int name = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_NAME);
int price = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_PRICE);
int quantity = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_QUANTITY);
String nameofsofa = cursor.getString(name);
String priceofsofa = cursor.getString(price);
String quantityofsofa = cursor.getString(quantity);
sofaname.setText(nameofsofa);
sofaprice.setText(priceofsofa);
quantitynumber.setText(quantityofsofa);
}
}
#Override
public void onLoaderReset(#NotNull Loader<Cursor> loader) {
sofaname.setText("");
sofaprice.setText("");
quantitynumber.setText("");
}
As your query is effectively
SELECT SUM(price) FROM orders;
Only a single column will be returned, thus using total = cursor.getInt(4); should result in an exception as the column is out of bounds, there will only be 1 column and it's index will be 0.
Thus try changing to use :-
public int getTotalExpenses()
{
int total = 0;
SQLiteDatabase database = this.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT SUM("+ OrderContract.OrderEntry.COLUMN_PRICE + ") FROM " + OrderContract.OrderEntry.TABLE_NAME, null);
if (cursor.moveToFirst())
{
total = cursor.getInt(0); //<<<<<<<<<< CHANGED
}
//while (cursor.moveToNext()); //<<<<<<<<<< COMMENTED OUT NOT NEEDED
cursor.close(); //<<<<<<<<<< ADDED should always close cursor when finished with them
return total;
}
I have an error when I try to read a table. I have a database with several table but my uri seems to not match.
My Content Provider :
public class CardContentProvider extends ContentProvider {
private StockCard stock;
public static String authority = "com.example.jean.cartememoire.CardContentProvider";
private static String path ="Cartes_table";
public static final String _ID = "_id";
public static final String THEME = "THEME";
public static final String QUESTION = "QUESTION";
public static final String REPONSE = "REPONSE";
public static final String DIFFICULTE = "DIFFICULTE"; //# = un chiffre
public static final String STOCK_TABLE = "Cartes_table";
public static final String STOCK_FACILE = "";
public static final String STOCK_NORMAL = "Cartes_tableCartes_table_facile_normal";
public static final String STOCK_DIFFICILE = "Cartes_table_difficile";
public static final String STOCK_EXTREME = "Cartes_table_extreme";
public static final String STOCK_IMPOSSIBLE = "Cartes_table_impossible";
private static final int ID_STOCK_TABLE = 1;
public static final int ID_FACILE = 2;
public static final int ID_NORMAL = 3;
public static final int ID_DIFFICILE = 4;
public static final int ID_EXTREME = 5;
public static final int ID_IMPOSSIBLE = 6;
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
matcher.addURI(authority, STOCK_TABLE, ID_STOCK_TABLE);
matcher.addURI(authority, STOCK_TABLE+"/*", ID_STOCK_TABLE);
matcher.addURI(authority, STOCK_FACILE+"/*", ID_FACILE);
matcher.addURI(authority, STOCK_NORMAL+"/*", ID_NORMAL);
matcher.addURI(authority, STOCK_DIFFICILE+"/*", ID_DIFFICILE);
matcher.addURI(authority, STOCK_EXTREME+"/*", ID_EXTREME);
matcher.addURI(authority, STOCK_IMPOSSIBLE+"/*", ID_IMPOSSIBLE);
}
#Override
public boolean onCreate() {
stock = StockCard.getInstance(getContext());
return true;
}
#Nullable
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = stock.getReadableDatabase();
int code = matcher.match(uri);
Cursor cursor;
switch (code)
{
case ID_STOCK_TABLE:
Log.d("Uri provider = "+code+" ", uri.toString()+" ");
cursor = db.query(STOCK_TABLE, projection, selection,
selectionArgs, null, null, sortOrder);
break;
case ID_FACILE:
cursor = db.query(STOCK_FACILE, projection, selection,
selectionArgs, null, null, sortOrder);
break;
case ID_NORMAL:
cursor = db.query(STOCK_NORMAL, projection, selection,
selectionArgs, null, null, sortOrder);
break;
case ID_DIFFICILE:
cursor = db.query(STOCK_DIFFICILE, projection, selection,
selectionArgs, null, null, sortOrder);
break;
case ID_EXTREME:
cursor = db.query(STOCK_EXTREME, projection, selection,
selectionArgs, null, null, sortOrder);
break;
case ID_IMPOSSIBLE:
cursor = db.query(STOCK_IMPOSSIBLE, projection, selection,
selectionArgs, null, null, sortOrder);
break;
default:
//long u = ContentUris.parseId(uri);
Log.d("Uri provider = "+code+" ", uri.toString()+" ");
throw new UnsupportedOperationException("Pas encore implémenté");
}
return cursor;
}
#Nullable
#Override
public String getType(Uri uri) {
return null;
}
#Nullable
#Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = stock.getWritableDatabase();
int code = matcher.match(uri);
long id;
Uri.Builder builder = new Uri.Builder();
switch(code)
{
case ID_STOCK_TABLE:
id = db.insert(STOCK_TABLE, null, values);
builder.appendPath(STOCK_TABLE);
break;
case ID_FACILE:
id = db.insert(STOCK_FACILE, null, values);
builder.appendPath(STOCK_FACILE);
break;
case ID_NORMAL:
id = db.insert(STOCK_NORMAL, null, values);
builder.appendPath(STOCK_NORMAL);
break;
case ID_DIFFICILE:
id = db.insert(STOCK_DIFFICILE, null, values);
builder.appendPath(STOCK_DIFFICILE);
break;
case ID_EXTREME:
id = db.insert(STOCK_EXTREME, null, values);
builder.appendPath(STOCK_EXTREME);
break;
case ID_IMPOSSIBLE:
id = db.insert(STOCK_IMPOSSIBLE, null, values);
builder.appendPath(STOCK_IMPOSSIBLE);
break;
default:
throw new UnsupportedOperationException("Pas encore implémenté");
}
builder.authority(authority);
builder = ContentUris.appendId(builder, id);
return builder.build();
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = stock.getWritableDatabase();
int code = matcher.match(uri);
int i;
long id;
switch(code)
{
case ID_STOCK_TABLE:
id = ContentUris.parseId(uri);
i = db.delete(STOCK_TABLE, "_id=" + id, null);
break;
case ID_FACILE:
id = ContentUris.parseId(uri);
i = db.delete(STOCK_FACILE, "_id=" + id, null);
break;
case ID_NORMAL:
id = ContentUris.parseId(uri);
i = db.delete(STOCK_NORMAL, "_id=" + id, null);
break;
case ID_DIFFICILE:
id = ContentUris.parseId(uri);
i = db.delete(STOCK_DIFFICILE, "_id=" + id, null);
break;
case ID_EXTREME:
id = ContentUris.parseId(uri);
i = db.delete(STOCK_EXTREME, "_id=" + id, null);
break;
case ID_IMPOSSIBLE:
id = ContentUris.parseId(uri);
i = db.delete(STOCK_IMPOSSIBLE, "_id=" + id, null);
break;
default:
throw new UnsupportedOperationException("Pas encore implémenté");
}
return 0;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
My Fragment class that contains my Loader, in my function databaseview, I put my rows inside a List View :
public class ViewDeck extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
public static final String authority = "com.example.jean.cartememoire.CardContentProvider";
public String[] from;
public final int[] to = {R.id.idList, R.id.themeList, R.id.questionList, R.id.reponseList, R.id.difficultList};
StockCard stock;
ViewGroup container;
ListView listView;
SimpleCursorAdapter adapter;
Cursor cursor;
private String focus;
private ArrayList<String> data = new ArrayList<String>();
private String table_name;
public ViewDeck()
{
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup c,
Bundle savedInstanceState) {
container = c;
View view = inflater.inflate(R.layout.fragment_view_card_editor, container, false);
stock = StockCard.getInstance(container.getContext());
from = new String[]{stock._ID,
stock.THEME,
stock.QUESTION,
stock.REPONSE,
stock.DIFFICULTE};
// Inflate the layout for this fragment
if (container != null) {
container.removeAllViews();
}
Bundle f = getArguments();
focus = getStockName(f.getInt("f"));
databaseView(view);
return view;
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri.Builder builder = new Uri.Builder();
Uri uri = builder.scheme("content").authority(authority)
.appendPath("Cartes_table_facile").build();
System.out.println("URI : "+uri.toString());
//Log.d("Uri provider = "+code+" ", uri.toString()+" ");
return new CursorLoader(container.getContext(), uri, from,
null, null, null);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
public String getStockName(int d)
{
switch(d+1)
{
case CardContentProvider.ID_FACILE:
return CardContentProvider.STOCK_FACILE;
case CardContentProvider.ID_NORMAL:
return CardContentProvider.STOCK_NORMAL;
case CardContentProvider.ID_DIFFICILE:
return CardContentProvider.STOCK_DIFFICILE;
case CardContentProvider.ID_EXTREME:
return CardContentProvider.STOCK_EXTREME;
case CardContentProvider.ID_IMPOSSIBLE:
return CardContentProvider.STOCK_IMPOSSIBLE;
default:
throw new UnsupportedOperationException("Difficulté inconnue");
}
}
public void databaseView(View view)
{
listView = (ListView) view.findViewById(R.id.listView);
System.out.println("DANS DATABASEVIEW");
adapter = new SimpleCursorAdapter(container.getContext(), R.layout.card_stock, null, from, to,0);
listView.setAdapter(adapter);
if(cursor != null)
cursor.close();
LoaderManager manager = getLoaderManager();
manager.initLoader(0, null, this);
if(cursor != null)
cursor.close();
System.out.println("CA GAZ");
}
}
EDIT : My error :
01-04 17:45:45.507 28655-28691/? E/AndroidRuntime: FATAL EXCEPTION: ModernAsyncTask #1
Process: com.example.jean.cartememoire, PID: 28655
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:153)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.UnsupportedOperationException: Pas encore implémenté
at com.example.jean.cartememoire.CardContentProvider.query(CardContentProvider.java:101)
at android.content.ContentProvider.query(ContentProvider.java:1017)
at android.content.ContentProvider$Transport.query(ContentProvider.java:238)
at android.content.ContentResolver.query(ContentResolver.java:491)
at android.support.v4.content.ContentResolverCompatJellybean.query(ContentResolverCompatJellybean.java:29)
at android.support.v4.content.ContentResolverCompat$ContentResolverCompatImplJB.query(ContentResolverCompat.java:57)
at android.support.v4.content.ContentResolverCompat.query(ContentResolverCompat.java:125)
at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:59)
at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:37)
at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:296)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:54)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:42)
at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:133)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
I have the next Content Provider
To insert a row in Table AGENDA, I do:
ContentValues values = new ContentValues(1);
values.put("MSG", "test");
context.getContentResolver().insert(DataProvider.CONTENT_URI_AGENDA, values);
and all works well.
But now, I´d like to use the uri with AGENDA_INSERTWITHCONFLICT to insert a row.
Please, How can I modify the line :
context.getContentResolver().insert(DataProvider.CONTENT_URI_AGENDA, values);
to do it?
Here is my Provider:
public class DataProvider extends ContentProvider {
public static final String TAGPROVIDER = "net.techabout.medappointment.provider";
public static final Uri CONTENT_URI_AGENDA = Uri.parse("content://"+TAGPROVIDER+"/agenda");
public static final String TABLE_AGENDA = "agenda";
private DbHelper dbHelper;
private static final int AGENDA_ALLROWS = 5;
private static final int AGENDA_INSERTWITHCONFLICT=7;
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(TAGPROVIDER, "agenda", AGENDA_ALLROWS);
uriMatcher.addURI(TAGPROVIDER, "agenda", AGENDA_INSERTWITHCONFLICT);
}
#Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
long id;
switch (uriMatcher.match(uri)) {
case AGENDA_ALLROWS:
id = db.insertOrThrow(TABLE_AGENDA, null, values);
break;
case AGENDA_INSERTWITHCONFLICT:
id=db.insertWithOnConflict(TABLE_AGENDA, BaseColumns._ID, values, SQLiteDatabase.CONFLICT_REPLACE);
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
Uri insertUri = ContentUris.withAppendedId(uri, id);
getContext().getContentResolver().notifyChange(insertUri, null);
return insertUri;
}
}
make following changes, Please use naming convetions as required.
// content provider
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(TAGPROVIDER, "agenda", AGENDA_ALLROWS);
uriMatcher.addURI(TAGPROVIDER, "agenda_insert_conflicts", AGENDA_INSERTWITHCONFLICT);
}
calling mechanism
String URL = "net.techabout.medappointment.provider/agenda_insert_conflicts";
Uri uri = Uri.parse(URL);
context.getContentResolver().insert(uri , values);
it's the first time I'm using the content provider.
so I have this:
public class ContactsContentProvider extends ContentProvider {
private ContactsDatabaseHelper dbHelper;
private static final UriMatcher uriMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
private static final int ONE_CONTACT = 1;
private static final int CONTACTS = 2;
private static final int CONTACT = 3;
static {
uriMatcher.addURI(ContactsDatabaseDescription.AUTHORITY,
Contact.TABLE_NAME + "/#", ONE_CONTACT);
uriMatcher.addURI(ContactsDatabaseDescription.AUTHORITY,
Contact.TABLE_NAME, CONTACTS);
uriMatcher.addURI(ContactsDatabaseDescription.AUTHORITY,
Contact.TABLE_NAME + "/*" , CONTACT);
}
#Override
public boolean onCreate() {
dbHelper = new ContactsDatabaseHelper(getContext());
return true;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(Contact.TABLE_NAME);
switch (uriMatcher.match(uri)) {
case ONE_CONTACT:
queryBuilder.appendWhere(
Contact._ID + "=" + uri.getLastPathSegment());
break;
case CONTACTS:
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_query_uri) + uri);
}
Cursor cursor = queryBuilder.query(dbHelper.getReadableDatabase(),
projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
// insert a new contact in the database
#Override
public Uri insert(Uri uri, ContentValues values) {
Uri newContactUri = null;
switch (uriMatcher.match(uri)) {
case CONTACTS:
// insert the new contact--success yields new contact's row id
long rowId = dbHelper.getWritableDatabase().insert(
Contact.TABLE_NAME, null, values);
if (rowId > 0) {
newContactUri = Contact.buildContactUri(rowId);
getContext().getContentResolver().notifyChange(uri, null);
}
else
throw new SQLException(
getContext().getString(R.string.insert_failed) + uri);
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_insert_uri) + uri);
}
return newContactUri;
}
#Override
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
int numberOfRowsUpdated; // 1 if update successful; 0 otherwise
switch (uriMatcher.match(uri)) {
case ONE_CONTACT:
String id = uri.getLastPathSegment();
numberOfRowsUpdated = dbHelper.getWritableDatabase().update(
Contact.TABLE_NAME, values, Contact._ID + "=" + id,
selectionArgs);
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_update_uri) + uri);
}
if (numberOfRowsUpdated != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return numberOfRowsUpdated;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int numberOfRowsDeleted;
switch (uriMatcher.match(uri)) {
case ONE_CONTACT:
String id = uri.getLastPathSegment();
numberOfRowsDeleted = dbHelper.getWritableDatabase().delete(
Contact.TABLE_NAME, Contact._ID + "=" + id, selectionArgs);
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_delete_uri) + uri);
}
if (numberOfRowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return numberOfRowsDeleted;
}
}
My database is
public class ContactsDatabaseDescription {
public static final String AUTHORITY =
"com.example.afran.bdcontacts.data";
private static final Uri BASE_CONTENT_URI =
Uri.parse("content://" + AUTHORITY);
public static final class Contact implements BaseColumns {
public static final String TABLE_NAME = "contacts"; // table's name
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendPath(TABLE_NAME).build();
public static final String COLUMN_FIRST_NAME = "firstName";
public static final String COLUMN_LAST_NAME = "lastName";
public static final String COLUMN_EMAIL = "email";
public static final String COLUMN_TYPE = "type";
public static Uri buildContactUri(long id) {
return ContentUris.withAppendedId(CONTENT_URI, id);
}
}
}
and on this fragment I read one last name (search) and I want to find the contact and I do not know how
public class DetailFragment extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor> {
public interface DetailFragmentListener {
void onContactDeleted();
void onEditContact(Uri contactUri);
}
private static final int CONTACT_LOADER = 0;
private DetailFragmentListener listener;
private Uri contactUri;
private TextView prenomTextView;
private TextView nomTextView;
private TextView emailTextView;
private TextView typeTextView;
#Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (DetailFragmentListener) context;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
setHasOptionsMenu(true);
Bundle arguments = getArguments();
if (arguments != null)
contactUri = arguments.getParcelable(MainActivity.CONTACT_URI);
View view =
inflater.inflate(R.layout.fragment_detail, container, false);
prenomTextView = (TextView) view.findViewById(R.id.firstNameTextView);
nomTextView = (TextView) view.findViewById(R.id.lastNameTextView);
emailTextView = (TextView) view.findViewById(R.id.emailTextView);
typeTextView = (TextView) view.findViewById(R.id.typeTextView);
getLoaderManager().initLoader(CONTACT_LOADER, null, this);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_edit:
listener.onEditContact(contactUri);
return true;
case R.id.action_delete:
deleteContact();
return true;
case R.id.action_search:
searchContact();
return true;
}
return super.onOptionsItemSelected(item);
}
private void searchContact() {
final EditText input = new EditText(getContext());
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.menuitem_recherche);
builder.setMessage(R.string.label_lastName);
builder.setView(input);
builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString();
return;
}
});
builder.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
return;
}
});
builder.create().show();
}
private void deleteContact() {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.confirm_title);
builder.setMessage(R.string.confirm_message);
builder.setPositiveButton(R.string.button_delete, new DialogInterface.OnClickListener() {
#Override
public void onClick(
DialogInterface dialog, int button) {
getActivity().getContentResolver().delete(
contactUri, null, null);
listener.onContactDeleted();
}
}
);
builder.setNegativeButton(R.string.button_cancel, null);
builder.create().show();
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader cursorLoader;
switch (id) {
case CONTACT_LOADER:
cursorLoader = new CursorLoader(getActivity(),
contactUri,
null,
null,
null,
null);
break;
default:
cursorLoader = null;
break;
}
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data != null && data.moveToFirst()) {
int firstIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_FIRST_NAME);
int lastIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_LAST_NAME);
int emailIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_EMAIL);
int typeIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_TYPE);
prenomTextView.setText(data.getString(firstIndex));
nomTextView.setText(data.getString(lastIndex));
emailTextView.setText(data.getString(emailIndex));
typeTextView.setText(data.getString(typeIndex));
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) { }
}
It is simple to search for a match of any column in your table. You simply need the contentUri, and where and whereArgs parameters for the query. Ensure your Uri points to the whole table. Assuming you want to match columns called "first_name" and "surname" with Strings called firstName and surname.
String where = "first_name =? and surname =?";
String[] whereArgs = {firstName, surname};
You can use parentheses and "and" and "or" to construct more complex queries. With numerical fields you can use > and < etc. You must ensure whereArgs has as many elements as where has "?"
I want to ask, if is there some way to get ParseObjects to Search suggestions-box in Android. I've succesully created recent-query suggestions and it worked well. But right now do I need to put there one string collection from Parse.com while the user is typing -show results, which contain the query which is being typed. I am kind of desperated because I've been searching for it for a week and no result.
Do you have any idea, how to accomplish that?
My in normal ParseQuery in SearchActivity:
ParseQuery<Animal> squery = ParseQuery.getQuery(Animal.class);
squery.whereMatches("animal", query, "i");
squery.findInBackground(new FindCallback<Animal>() {
#Override
public void done(List<Animal> animals, ParseException error) {
if(animals != null){
nAdapter.clear();
for (int i = 0; i < animals.size(); i++) {
mProgressBar = (ProgressBar) findViewById(R.id.search_loading_animals);
mProgressBar.setVisibility(View.INVISIBLE);
nAdapter.add(animals.get(i));
}
}
}
});
SuggestionAdapter to which do i need to implement the ParseQuery:
public class SuggestionProvider extends ContentProvider {
private static final String TAG = "SuggestionProvider";
private static final int SEARCH_SUGGESTIONS = 1;
private static final UriMatcher sURLMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
sURLMatcher.addURI("*", SearchManager.SUGGEST_URI_PATH_QUERY,
SEARCH_SUGGESTIONS);
sURLMatcher.addURI("*", SearchManager.SUGGEST_URI_PATH_QUERY + "/*",
SEARCH_SUGGESTIONS);
}
private static final String[] COLUMNS = new String[] {
"_id",
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
SearchManager.SUGGEST_COLUMN_QUERY
};
public SuggestionProvider() {
}
#Override
public boolean onCreate() {
return true;
}
#Override
public Cursor query(Uri url, String[] projectionIn, String selection,
String[] selectionArgs, String sort) {
int match = sURLMatcher.match(url);
switch (match) {
case SEARCH_SUGGESTIONS:
String query = url.getLastPathSegment();
MatrixCursor cursor = new MatrixCursor(COLUMNS);
String[] suffixes = { "", "a", " foo", "XXXXXXXXXXXXXXXXX" };
for (String suffix : suffixes) {
Toast.makeText(getContext(), "", Toast.LENGTH_SHORT).show();
addRow(cursor, query + suffix);
}
return cursor;
default:
throw new IllegalArgumentException("Unknown URL: " + url);
}
}
private void addRow(MatrixCursor cursor, String string) {
long id = cursor.getCount();
cursor.newRow().add(id).add(string).add(Intent.ACTION_SEARCH).add(string);
}
#Override
public String getType(Uri url) {
int match = sURLMatcher.match(url);
switch (match) {
case SEARCH_SUGGESTIONS:
return SearchManager.SUGGEST_MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URL: " + url);
}
}
#Override
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
throw new UnsupportedOperationException("update not supported");
}
#Override
public Uri insert(Uri url, ContentValues initialValues) {
throw new UnsupportedOperationException("insert not supported");
}
#Override
public int delete(Uri url, String where, String[] whereArgs) {
throw new UnsupportedOperationException("delete not supported");
}
}