MaddoScientisto
MaddoScientisto

Reputation: 189

Android Content Provider with multiple tables unknow uri error

I followed a tutorial about sqlite and content providers but it had only examples for a single table, I eventually managed to figure how to expand that provider to include two tables and everything seems to be working fine.
The app I'm trying to make as a self excercise has right now a todo mode and a notes mode, the classes are almost iedntical, the only difference is a few database column entries.
The todo mode (which was in the example) works perfectly, I can create new entries, view and delete them, while the notes mode can create and delete entries but for some bizarre reason it can't open them as it gives me an exception about the uri not being recognized.

This is the error I'm getting:

02-28 10:08:40.343: E/AndroidRuntime(20079): FATAL EXCEPTION: main
02-28 10:08:40.343: E/AndroidRuntime(20079): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jackomel.maddonote/com.jackomel.maddonote.NotesDetailActivity}: java.lang.IllegalArgumentException: Unknown URI: content://com.jackomel.maddonote.contentprovider/maddonote/1
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2304)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2354)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.ActivityThread.access$600(ActivityThread.java:150)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.os.Looper.loop(Looper.java:137)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.ActivityThread.main(ActivityThread.java:5191)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at java.lang.reflect.Method.invokeNative(Native Method)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at java.lang.reflect.Method.invoke(Method.java:511)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at dalvik.system.NativeStart.main(Native Method)
02-28 10:08:40.343: E/AndroidRuntime(20079): Caused by: java.lang.IllegalArgumentException: Unknown URI: content://com.jackomel.maddonote.contentprovider/maddonote/1
02-28 10:08:40.343: E/AndroidRuntime(20079):    at com.jackomel.maddonote.contentprovider.MyTodoContentProvider.query(MyTodoContentProvider.java:103)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.content.ContentProvider.query(ContentProvider.java:652)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.content.ContentProvider$Transport.query(ContentProvider.java:189)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.content.ContentResolver.query(ContentResolver.java:372)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.content.ContentResolver.query(ContentResolver.java:315)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at com.jackomel.maddonote.NotesDetailActivity.fillData(NotesDetailActivity.java:102)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at com.jackomel.maddonote.NotesDetailActivity.onCreate(NotesDetailActivity.java:56)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.Activity.performCreate(Activity.java:5104)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
02-28 10:08:40.343: E/AndroidRuntime(20079):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2258)
02-28 10:08:40.343: E/AndroidRuntime(20079):    ... 11 more

This is the content provider I have right now (skipping posting all the imports)

public class MyMaddoContentProvider extends ContentProvider {
// Database
private MaddoDatabaseHelper database;

// Used for urlMacher
private static final int TODOS = 10;
private static final int TODO_ID = 20;

private static final int NOTES = 11;
private static final int NOTE_ID = 21;

private static final String AUTHORITY = "com.jackomel.maddonote.contentprovider";

private static final String BASE_PATH = "maddo";
//private static final String NOTE_PATH = "notes";
public static final Uri TODO_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH + "todo");
public static final Uri NOTE_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH + "note");


public static final String CONTENT_TYPE_TODO = ContentResolver.CURSOR_DIR_BASE_TYPE + "/todos";
public static final String CONTENT_ITEM_TYPE_TODO = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/todo";

public static final String CONTENT_TYPE_NOTE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/notes";
public static final String CONTENT_ITEM_TYPE_NOTE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/note";

public static final String[] todoAvailable = { TodoTable.COLUMN_CATEGORY,
        TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_DESCRIPTION,
        TodoTable.COLUMN_ID };
public static final String[] noteAvailable = { NotesTable.COLUMN_CATEGORY,
    NotesTable.COLUMN_SUMMARY, NotesTable.COLUMN_CONTENT, NotesTable.COLUMN_DATE,
    TodoTable.COLUMN_ID 

};

private static final UriMatcher sURIMatcher = new UriMatcher(
        UriMatcher.NO_MATCH);
static {
    sURIMatcher.addURI(AUTHORITY, BASE_PATH + "todo", TODOS);
    sURIMatcher.addURI(AUTHORITY, BASE_PATH + "todo" + "/#", TODO_ID);

    sURIMatcher.addURI(AUTHORITY, BASE_PATH + "note", NOTES);
    sURIMatcher.addURI(AUTHORITY, BASE_PATH + "note" + "/#", NOTE_ID);
}

@Override
public boolean onCreate() {
    database = new MaddoDatabaseHelper(getContext());
    return false;
}

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

    // Using SQLiteQueryBuilder instead of query() method
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

    // Check if the caller has requested a column which does not exists
    //checkColumns(projection);

    // Set the table
    //queryBuilder.setTables(TodoTable.TABLE_NAME);

    int uriType = sURIMatcher.match(uri);
    checkColumns(projection, uriType);
    switch (uriType) {
    case TODOS:
        queryBuilder.setTables(TodoTable.TABLE_NAME);
        break;
    case TODO_ID:
        queryBuilder.setTables(TodoTable.TABLE_NAME);
        // Adding the ID to the original query
        queryBuilder.appendWhere(TodoTable.COLUMN_ID + "="
                + uri.getLastPathSegment());
        break;
    case NOTES:
        queryBuilder.setTables(NotesTable.TABLE_NAME);
        break;
    case NOTE_ID:
        queryBuilder.setTables(NotesTable.TABLE_NAME);
        queryBuilder.appendWhere(NotesTable.COLUMN_ID + "=" + uri.getLastPathSegment());

    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }

    SQLiteDatabase db = database.getWritableDatabase();
    Cursor cursor = queryBuilder.query(db, projection, selection,
            selectionArgs, null, null, sortOrder);
    // Make sure that potential listeners are getting notified
    cursor.setNotificationUri(getContext().getContentResolver(), uri);

    return cursor;
}

@Override
public String getType(Uri uri) {
    return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    int uriType = sURIMatcher.match(uri);
    SQLiteDatabase sqlDB = database.getWritableDatabase();
    int rowsDeleted = 0;
    long id = 0;
    String curPath;
    switch (uriType) {
    case TODOS:
        System.out.println("Inserimento in tabella TODOS");
        id = sqlDB.insert(TodoTable.TABLE_NAME, null, values);
        curPath = "todo";
        break;
    case NOTES:
        System.out.println("Inserimento in tabella NOTES");
        id = sqlDB.insert(NotesTable.TABLE_NAME, null, values);
        curPath = "note";
        break;
    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return Uri.parse(BASE_PATH + curPath + "/" + id);
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    int uriType = sURIMatcher.match(uri);
    SQLiteDatabase sqlDB = database.getWritableDatabase();
    int rowsDeleted = 0;
            String id;
    switch (uriType) {
    case NOTES:
        rowsDeleted = sqlDB.delete(NotesTable.TABLE_NAME, selection, selectionArgs);
        break;
    case NOTE_ID:
        id = uri.getLastPathSegment();
        if (TextUtils.isEmpty(selection)) {
            rowsDeleted = sqlDB.delete(NotesTable.TABLE_NAME, NotesTable.COLUMN_ID + "=" + id, null);
        } else {
            rowsDeleted = sqlDB.delete(NotesTable.TABLE_NAME, NotesTable.COLUMN_ID + "=" + 
        id + " and " + selection, selectionArgs);
            break;
        }

    case TODOS:
        rowsDeleted = sqlDB.delete(TodoTable.TABLE_NAME, selection,
                selectionArgs);
        break;
    case TODO_ID:
        id = uri.getLastPathSegment();
        if (TextUtils.isEmpty(selection)) {
            rowsDeleted = sqlDB.delete(TodoTable.TABLE_NAME,
                    TodoTable.COLUMN_ID + "=" + id, null);
        } else {
            rowsDeleted = sqlDB.delete(TodoTable.TABLE_NAME,
                    TodoTable.COLUMN_ID + "=" + id + " and " + selection,
                    selectionArgs);
        }
        break;
    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsDeleted;
}

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

    int uriType = sURIMatcher.match(uri);
    SQLiteDatabase sqlDB = database.getWritableDatabase();
    int rowsUpdated = 0;
    String id;
    switch (uriType) {
    case NOTES:
        rowsUpdated = sqlDB.update(NotesTable.TABLE_NAME, values, selection, selectionArgs);
        break;
    case NOTE_ID:
        id = uri.getLastPathSegment();
        if (TextUtils.isEmpty(selection)) {
            rowsUpdated = sqlDB.update(NotesTable.TABLE_NAME, values, 
                    NotesTable.COLUMN_ID + "=" + id, null);
        } else {
            rowsUpdated = sqlDB.update(TodoTable.TABLE_NAME, values,
                    NotesTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
        }
        break;
    case TODOS:
        rowsUpdated = sqlDB.update(TodoTable.TABLE_NAME, values, selection,
                selectionArgs);
        break;
    case TODO_ID:
        id = uri.getLastPathSegment();
        if (TextUtils.isEmpty(selection)) {
            rowsUpdated = sqlDB.update(TodoTable.TABLE_NAME, values,
                    TodoTable.COLUMN_ID + "=" + id, null);
        } else {
            rowsUpdated = sqlDB.update(TodoTable.TABLE_NAME, values,
                    TodoTable.COLUMN_ID + "=" + id + " and " + selection,
                    selectionArgs);
        }
        break;
    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}

private void checkColumns(String[] projection, int uriType) { 

    if (projection != null) {
        HashSet<String> requestedColumns = new HashSet<String>(
                Arrays.asList(projection));
        HashSet<String> availableColumns = null;
        switch (uriType) {
        case TODOS: case TODO_ID:
            availableColumns = new HashSet<String>(
                    Arrays.asList(todoAvailable));
        break;
        case NOTES: case NOTE_ID:
            availableColumns = new HashSet<String>(
                    Arrays.asList(noteAvailable));
            break;

        }

        // Check if all columns which are requested are available
        if (!availableColumns.containsAll(requestedColumns)) {
            throw new IllegalArgumentException(
                    "Unknown columns in projection");
        }
    }
}
}

And these are the activities in which the error is caused (again skipping imports):

public class NotesOverviewActivity extends ListActivity implements
LoaderManager.LoaderCallbacks<Cursor>{

private static final int ACTIVITY_CREATE = 0;
private static final int ACTIVITY_EDIT = 1;
private static final int DELETE_ID = Menu.FIRST + 1;
// private Cursor cursor;
private SimpleCursorAdapter adapter;

/** Called when the activity is first created. */

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.notes_list);
    this.getListView().setDividerHeight(2);
    fillData();
    registerForContextMenu(getListView());
}

// Create the menu based on the XML defintion
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.listmenu, menu);
    return true;
}

// Reaction to the menu selection
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.insert:
        createNote();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case DELETE_ID:
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
                .getMenuInfo();
        Uri uri = Uri.parse(MyMaddoContentProvider.NOTE_URI + "/"
                + info.id);
        getContentResolver().delete(uri, null, null);
        fillData();
        return true;
    }
    return super.onContextItemSelected(item);
}

private void createNote() {
    Intent i = new Intent(this, NotesDetailActivity.class);
    startActivity(i);
}

// Opens the second activity if an entry is clicked
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    Intent i = new Intent(this, NotesDetailActivity.class);
    Uri notesUri = Uri.parse(MyMaddoContentProvider.NOTE_URI + "/" + id);
    i.putExtra(MyMaddoContentProvider.CONTENT_ITEM_TYPE_NOTE, notesUri);

    startActivity(i);
}

private void fillData() {

    // Fields from the database (projection)
    // Must include the _id column for the adapter to work
    String[] from = new String[] { NotesTable.COLUMN_SUMMARY };
    // Fields on the UI to which we map
    int[] to = new int[] { R.id.label };

    getLoaderManager().initLoader(0, null, this);
    adapter = new SimpleCursorAdapter(this, R.layout.notes_row, null, from,
            to, 0);

    setListAdapter(adapter);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}

// Creates a new loader after the initLoader () call
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String[] projection = { NotesTable.COLUMN_ID, NotesTable.COLUMN_SUMMARY };
    CursorLoader cursorLoader = new CursorLoader(this,
            MyMaddoContentProvider.NOTE_URI, projection, null, null, null);
    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    adapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    // data is not available anymore, delete reference
    adapter.swapCursor(null);
}

}

the error seems to happen in the onListenClick method, right after it starts the notesDetailActivity, which I'm including below

public class NotesDetailActivity extends Activity {

private Spinner mCategory;
private EditText mTitleText;
private EditText mBodyText;
private EditText mDateText;

private Uri noteUri;

@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.notes_edit);

    mCategory = (Spinner) findViewById(R.id.category);
    mTitleText = (EditText) findViewById(R.id.todo_edit_summary);
    mBodyText = (EditText) findViewById(R.id.todo_edit_description);
    mDateText = (EditText)findViewById(R.id.date); 
    mDateText.setText(java.text.DateFormat.getTimeInstance().format(Calendar.getInstance().getTime()));
    Button confirmButton = (Button) findViewById(R.id.todo_edit_button);

    Bundle extras = getIntent().getExtras();

    // Check from the saved Instance
    noteUri = (bundle == null) ? null : (Uri) bundle
            .getParcelable(MyMaddoContentProvider.CONTENT_ITEM_TYPE_NOTE);

    // Or passed from the other activity
    if (extras != null) {
        noteUri = extras
                .getParcelable(MyMaddoContentProvider.CONTENT_ITEM_TYPE_NOTE);

        fillData(noteUri);
    }

    confirmButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            if (TextUtils.isEmpty(mTitleText.getText().toString())) {
                makeToast();
            } else {
                setResult(RESULT_OK);
                finish();
            }
        }

    });
}

// Create the menu based on the XML defintion
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.detailsmenu, menu);
        return true;
    }

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.save:
        saveData();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public void saveData() {
    if (TextUtils.isEmpty(mTitleText.getText().toString())) {
        makeToast();
    } else {
        setResult(RESULT_OK);
        finish();
    }
}

private void fillData(Uri uri) {
    String[] projection = { NotesTable.COLUMN_SUMMARY,
            NotesTable.COLUMN_CONTENT, NotesTable.COLUMN_CATEGORY, NotesTable.COLUMN_DATE };
    Cursor cursor = getContentResolver().query(uri, projection, null, null,
            null);
    if (cursor != null) {
        cursor.moveToFirst();
        String category = cursor.getString(cursor
                .getColumnIndexOrThrow(NotesTable.COLUMN_CATEGORY));

        for (int i = 0; i < mCategory.getCount(); i++) {

            String s = (String) mCategory.getItemAtPosition(i);
            if (s.equalsIgnoreCase(category)) {
                mCategory.setSelection(i);
            }
        }

        mTitleText.setText(cursor.getString(cursor
                .getColumnIndexOrThrow(NotesTable.COLUMN_SUMMARY)));
        mBodyText.setText(cursor.getString(cursor
                .getColumnIndexOrThrow(NotesTable.COLUMN_CONTENT)));
        mDateText.setText(cursor.getString(cursor
                .getColumnIndexOrThrow(NotesTable.COLUMN_DATE)));

        // Always close the cursor
        cursor.close();
    }
}

protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    saveState();
    outState.putParcelable(MyMaddoContentProvider.CONTENT_ITEM_TYPE_NOTE, noteUri);
}

@Override
protected void onPause() {
    super.onPause();
    saveState();
}

private void saveState() {
    String category = (String) mCategory.getSelectedItem();
    String summary = mTitleText.getText().toString();
    String description = mBodyText.getText().toString();
    String date = mBodyText.getText().toString();

    // Only save if either summary or description
    // is available

    if (description.length() == 0 && summary.length() == 0) {
        return;
    }

    ContentValues values = new ContentValues();
    values.put(NotesTable.COLUMN_CATEGORY, category);
    values.put(NotesTable.COLUMN_SUMMARY, summary);
    values.put(NotesTable.COLUMN_CONTENT, description);
    values.put(NotesTable.COLUMN_DATE, date);

    if (noteUri == null) {
        // New note
        noteUri = getContentResolver().insert(
                MyMaddoContentProvider.NOTE_URI, values);
    } else {
        // Update note
        getContentResolver().update(noteUri, values, null, null);
    }
}

private void makeToast() {
    Toast.makeText(NotesDetailActivity.this, "Please maintain a summary",
            Toast.LENGTH_LONG).show();
}

}

I'm obviously doing something wrong with the uri, still no idea exactly what, considering the todo part is almost exactly the same (save for variable names and database table of course) and doesn't give such errors.
What is the problem?

Upvotes: 3

Views: 3236

Answers (2)

starsg38
starsg38

Reputation: 31

I think I may have found a solution to this problem. I was having a similar problem except for my error was saying that I had invalid tables instead of URI's. I followed Jackomels example above for his set tables queries and was able to get my edit to work. His Uri's are set up differently than mine which I am thinking is what the error is about. He uses the same BASE_PATH for both tables but I think that each table needs to have a different "base path".

I have private static final String BASE_PATH = "todos" & private static final String DEVICE_PATH = "devices";

I am pasting my code below in case it helps someone else.

package com.cossioinsurance.rentalsafety.contentprovider2;
import java.util.Arrays;
import java.util.HashSet;

import com.cossioinsurance.rentalsafety.database.TodoDatabaseHelper;
import com.cossioinsurance.rentalsafety.database.NoteTable;
import com.cossioinsurance.rentalsafety.database.DeviceTable;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class MyNoteContentProvider extends ContentProvider{

	  // database
	  private TodoDatabaseHelper database;

	  // used for the UriMacher
	  private static final int TODOS = 10;
	  private static final int TODO_ID = 20;
	  private static final int DEVICES = 30;
	  private static final int DEVICE_ID = 40;

	  private static final String AUTHORITY = "com.cossioinsurance.rentalsafety.contentprovider2";

	  private static final String BASE_PATH = "todos";
	  private static final String DEVICE_PATH = "devices";
	  
	  public static final Uri CONTENT_URI_TODOS = Uri.parse("content://" + AUTHORITY
	      + "/" + BASE_PATH);
	  public static final Uri CONTENT_URI_DEVICES = Uri.parse("content://" + AUTHORITY
		      + "/" + DEVICE_PATH);

	  public static final String CONTENT_TYPE_TODOS = ContentResolver.CURSOR_DIR_BASE_TYPE
	      + "/todos";
	  public static final String CONTENT_TYPE_DEVICES = ContentResolver.CURSOR_DIR_BASE_TYPE
		      + "/devices";
	  
	  public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
	      + "/todo";
	  
	  public static final String CONTENT_ITEM_TYPE2 = ContentResolver.CURSOR_ITEM_BASE_TYPE
		      + "/device";

	  private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	  static {
	    sURIMatcher.addURI(AUTHORITY, BASE_PATH, TODOS);
	    sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", TODO_ID);
	    sURIMatcher.addURI(AUTHORITY, DEVICE_PATH, DEVICES);
	    sURIMatcher.addURI(AUTHORITY, DEVICE_PATH + "/#", DEVICE_ID);
	  }

	  @Override
	  public boolean onCreate() {
	    database = new TodoDatabaseHelper(getContext());
	    return false;
	  }

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

	    // Uisng SQLiteQueryBuilder instead of query() method
	    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

	    // check if the caller has requested a column which does not exists
	    checkColumns(projection);

	    // Set the table
	    

	    int uriType = sURIMatcher.match(uri);
	    switch (uriType) {
	    case TODOS:
	    	queryBuilder.setTables(NoteTable.TABLE_TODO);
	      break;
	    case TODO_ID:
	    	queryBuilder.setTables(NoteTable.TABLE_TODO);
	      // adding the ID to the original query
	      queryBuilder.appendWhere(NoteTable.COLUMN_ID + "="
	          + uri.getLastPathSegment());
	      break;
	    case DEVICES:
	    	queryBuilder.setTables(DeviceTable.TABLE_DEVICE);
	      break;
	    case DEVICE_ID:
	    	queryBuilder.setTables(DeviceTable.TABLE_DEVICE);
	      // adding the ID to the original query
	      queryBuilder.appendWhere(DeviceTable.COLUMN_ID + "="
	          + uri.getLastPathSegment());
	      break;
	    default:
	      throw new IllegalArgumentException("Unknown URI: " + uri);
	    }

	    SQLiteDatabase db = database.getWritableDatabase();
	    Cursor cursor = queryBuilder.query(db, projection, selection,
	        selectionArgs, null, null, sortOrder);
	    // make sure that potential listeners are getting notified
	    cursor.setNotificationUri(getContext().getContentResolver(), uri);

	    return cursor;
	  }

	  @Override
	  public String getType(Uri uri) {
	    return null;
	  }

	  @Override
	  public Uri insert(Uri uri, ContentValues values) {
	    int uriType = sURIMatcher.match(uri);
	    SQLiteDatabase sqlDB = database.getWritableDatabase();
	    int rowsDeleted = 0;
	    long id = 0;
	    switch (uriType) {
	    case TODOS:
	      id = sqlDB.insert(NoteTable.TABLE_TODO, null, values);
	      break;
	    case DEVICES:
		  id = sqlDB.insert(DeviceTable.TABLE_DEVICE, null, values);
		  break;
	    default:
	      throw new IllegalArgumentException("Unknown URI: " + uri);
	    }
	    getContext().getContentResolver().notifyChange(uri, null);
	    return Uri.parse(BASE_PATH + "/" + id);
	    
	
	  }

	  //Deleted Rows
	  
	  @Override
	  public int delete(Uri uri, String selection, String[] selectionArgs) {
	    int uriType = sURIMatcher.match(uri);
	    SQLiteDatabase sqlDB = database.getWritableDatabase();
	    int rowsDeleted = 0;  
	    String id = uri.getLastPathSegment();
	    switch (uriType) {
	    case TODOS:
	      rowsDeleted = sqlDB.delete(NoteTable.TABLE_TODO, selection,
	          selectionArgs);
	      break;
	    case TODO_ID:
	     
	      if (TextUtils.isEmpty(selection)) {
	        rowsDeleted = sqlDB.delete(NoteTable.TABLE_TODO,
	            NoteTable.COLUMN_ID + "=" + id, 
	            null);
	      } else {
	        rowsDeleted = sqlDB.delete(NoteTable.TABLE_TODO,
	            NoteTable.COLUMN_ID + "=" + id 
	            + " and " + selection,
	            selectionArgs);
	      }
	      break;
	    case DEVICES:
		      rowsDeleted = sqlDB.delete(DeviceTable.TABLE_DEVICE, selection,
		          selectionArgs);
		      break;
		    case DEVICE_ID:
		     
		      if (TextUtils.isEmpty(selection)) {
		        rowsDeleted = sqlDB.delete(DeviceTable.TABLE_DEVICE,
		            DeviceTable.COLUMN_ID + "=" + id, 
		            null);
		      } else {
		        rowsDeleted = sqlDB.delete(NoteTable.TABLE_TODO,
		            DeviceTable.COLUMN_ID + "=" + id 
		            + " and " + selection,
		            selectionArgs);
		      }
		      break;
	    default:
	      throw new IllegalArgumentException("Unknown URI: " + uri);
	    }
	    getContext().getContentResolver().notifyChange(uri, null);
	    return rowsDeleted;
	  }

	  
	  //Update Rows
	  @Override
	  public int update(Uri uri, ContentValues values, String selection,
	      String[] selectionArgs) {

	    int uriType = sURIMatcher.match(uri);
	    SQLiteDatabase sqlDB = database.getWritableDatabase();
	    int rowsUpdated = 0;
	    
	    switch (uriType) {
	    case TODOS:
	      rowsUpdated = sqlDB.update(NoteTable.TABLE_TODO, 
	          values, 
	          selection,
	          selectionArgs);
	      break;
	    case TODO_ID:
	    	String id = uri.getLastPathSegment();
	      if (TextUtils.isEmpty(selection)) {
	        rowsUpdated = sqlDB.update(NoteTable.TABLE_TODO, 
	            values,
	            NoteTable.COLUMN_ID + "=" + id, 
	            null);
	      } else {
	        rowsUpdated = sqlDB.update(NoteTable.TABLE_TODO, 
	            values,
	            NoteTable.COLUMN_ID + "=" + id 
	            + " and " 
	            + selection,
	            selectionArgs);
	      }
	      break;
	    case DEVICES:
		      rowsUpdated = sqlDB.update(DeviceTable.TABLE_DEVICE, 
		          values, 
		          selection,
		          selectionArgs);
		      break;
		    case DEVICE_ID:
		    	id = uri.getLastPathSegment();
		      if (TextUtils.isEmpty(selection)) {
		        rowsUpdated = sqlDB.update(DeviceTable.TABLE_DEVICE, 
		            values,
		            DeviceTable.COLUMN_ID + "=" + id, 
		            null);
		      } else {
		        rowsUpdated = sqlDB.update(DeviceTable.TABLE_DEVICE, 
		            values,
		            DeviceTable.COLUMN_ID + "=" + id 
		            + " and " 
		            + selection,
		            selectionArgs);
		      }
		      break;
	    default:
	      throw new IllegalArgumentException("Unknown URI: " + uri);
	    }
	    getContext().getContentResolver().notifyChange(uri, null);
	    return rowsUpdated;
	  }

	  private void checkColumns(String[] projection) {
	    String[] available = { NoteTable.COLUMN_CATEGORY,
	        NoteTable.COLUMN_SUMMARY, NoteTable.COLUMN_DESCRIPTION, NoteTable.COLUMN_EMAIL, NoteTable.COLUMN_RENTALDATES, 
	        NoteTable.COLUMN_ENDDATES, NoteTable.COLUMN_TIME, NoteTable.COLUMN_LOCATION, NoteTable.COLUMN_NOTES,
	        NoteTable.COLUMN_ID, DeviceTable.COLUMN_ID, DeviceTable.COLUMN_CATEGORY, DeviceTable.COLUMN_NAME, DeviceTable.COLUMN_TYPE };
	    if (projection != null) {
	      HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
	      HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
	      // check if all columns which are requested are available
	      if (!availableColumns.containsAll(requestedColumns)) {
	        throw new IllegalArgumentException("Unknown columns in projection");
	      }
	    }
	  }
}

Upvotes: 1

user1673567
user1673567

Reputation: 108

I have followed the same example.. Here is your fix--

change your authority name in both manifest and MyMaddoContentProvider class as follows:-

private static final String AUTHORITY = "com.jackomel.maddonote.contentprovide.MyMaddoContentProviderr";

and

android:name="com.jackomel.maddonote.contentprovider.MyMaddoContentProvider" 
android:authorities="com.jackomel.maddonote.contentprovider.MyMaddoContentProvider"

It should probably work now.

Upvotes: 2

Related Questions