具有多个表的Android内容提供程序unknow uri错误

时间:2013-02-28 09:37:55

标签: android android-contentprovider android-sqlite

我遵循了关于sqlite和内容提供程序的教程,但它只有一个表的示例,我最终设法计算如何扩展该提供程序以包含两个表,一切似乎都正常工作。
我正在尝试制作一个自我练习的应用程序现在有一个todo模式和一个音符模式,这些类几乎是非常的,唯一的区别是几个数据库列条目。
todo模式(在示例中)完美运行,我可以创建新条目,查看和删除它们,而notes模式可以创建和删除条目但是由于某些奇怪的原因它无法打开它们因为它给了我一个例外关于uri没有得到承认。

这是我得到的错误:

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

这是我现在拥有的内容提供商(跳过发布所有导入内容)

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");
        }
    }
}
}

这些是导致错误的活动(再次跳过导入):

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);
}

}

错误似乎发生在onListenClick方法中,就在它启动notesDetailActivity之后,我将在下面包含

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();
}

}

我显然对uri做了一些错误,仍然不知道究竟是什么,考虑到todo部分几乎完全相同(当然保存变量名和数据库表)并且不会出现这样的错误。 /> 有什么问题?

2 个答案:

答案 0 :(得分:2)

我遵循了相同的例子..这是你的修复 -

在manifest和MyMaddoContentProvider类中更改您的权限名称,如下所示: -

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

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

现在应该可以了。

答案 1 :(得分:1)

我想我可能找到了解决这个问题的方法。我有一个类似的问题,除了我的错误是说我有无效的表而不是URI的。我按照上面的Jackomels示例进行了他的set table查询,并且能够让我的编辑工作。他的Uri的设置与我的不同,我想的是错误是什么。他对两个表都使用相同的BASE_PATH,但我认为每个表需要有不同的“基本路径”。

我有私有静态最终字符串BASE_PATH =“todos”&amp; private static final String DEVICE_PATH =“devices”;

我正在粘贴我的代码,以防其他人帮助。

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");
	      }
	    }
	  }
}