具有多个表的Android内容提供程序未知URI错误

3
我参考了一个sqlite和内容提供程序的教程,但它只有单个表的示例。我最终设法扩展该提供程序以包括两个表,并且一切似乎都正常工作。
我正在尝试制作一个自我练习的应用程序,现在有待办事项模式和笔记模式,这两个类几乎相同,唯一的区别是一些数据库列条目。
待办事项模式(在示例中)工作得非常完美,我可以创建新条目、查看和删除它们,而笔记模式可以创建和删除条目,但由于未能识别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出了问题,但我不确定具体是什么原因,考虑到待办事项部分基本相同(当然变量名和数据库表格除外),却没有出现这样的错误。
问题出在哪里?


你在清单文件中发布了你的内容提供者吗? - rekire
是的,我做了: 另外,待办事项部分可以正常工作,并且具有相同的结构,不知道为什么笔记部分就是不行。 - MaddoScientisto
尝试将MyMaddoContentProvider中的private static final String BASE_PATH =“maddo”更改为private static final String BASE_PATH =“maddobase”,希望这样可以解决您的问题。请告诉我这是否解决了您的问题。 - Animesh Sinha
不,似乎并没有解决这个问题。 - MaddoScientisto
2个回答

2

我已经按照相同的示例进行了操作。这是您的修复方法 -

在清单和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"

现在应该可以正常工作了。

哇,我发了这个帖子已经4个月了,在此期间我放弃了那种方法,实际上我因为工作完全放弃了这个项目。不过,我会将其标记为答案,因为它可能会帮助到遇到同样问题的人。 谢谢,我猜。 - MaddoScientisto

1
我认为我可能已经找到了解决这个问题的方法。我的问题与此类似,但错误提示是说我有无效的表而不是URI。我按照Jackomel上面设置表查询的示例进行操作,成功让我的编辑工作了。他的URI设置与我的不同,我认为这就是出错的原因。他为两个表使用了相同的BASE_PATH,但我认为每个表都需要有一个不同的“基础路径”。
以下是我的代码,以防有助于其他人:

我有 private static final String BASE_PATH = "todos" 和 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");
       }
     }
   }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接