Как исправить URL-адрес поставщика контента, который не найден в поставщике контента Android?

Я выполнил приведенный ниже учебник http://www.vogella.de/articles/AndroidSQLite/article.htm

Но получив это исключение после нажатия кнопки подтверждения,

01-20 10:18:14.585: E/AndroidRuntime(2006): Caused by: java.lang.IllegalArgumentException: Unknown URL content://com.example.todos.contentprovider/todos
01-20 10:18:14.585: E/AndroidRuntime(2006):     at android.content.ContentResolver.insert(ContentResolver.java:910)
01-20 10:18:14.585: E/AndroidRuntime(2006):     at com.example.todos.TodoDetailActivity.saveState(TodoDetailActivity.java:122)
01-20 10:18:14.585: E/AndroidRuntime(2006):     at com.example.todos.TodoDetailActivity.onPause(TodoDetailActivity.java:100)

TodoDetailActivity

public class TodoDetailActivity extends Activity {

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

    private Uri todoUri;

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

        mCategory = (Spinner) findViewById(R.id.category);
        mTitleText = (EditText) findViewById(R.id.todo_edit_summary);
        mBodyText = (EditText) findViewById(R.id.todo_edit_description);
        Button confirmButton = (Button) findViewById(R.id.todo_edit_button);

        Bundle extras = getIntent().getExtras();

        // check from the saved Instance
        todoUri = (bundle == null) ? null : (Uri) bundle
                .getParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE);

        // Or passed from the other activity
        if (extras != null) {
            todoUri = extras
                    .getParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE);

            fillData(todoUri);
        }

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

        });
    }

    private void fillData(Uri uri) {
        String[] projection = { TodoTable.COLUMN_SUMMARY,
                TodoTable.COLUMN_DESCRIPTION, TodoTable.COLUMN_CATEGORY };
        Cursor cursor = getContentResolver().query(uri, projection, null, null,
                null);
        if (cursor != null) {
            cursor.moveToFirst();
            String category = cursor.getString(cursor
                    .getColumnIndexOrThrow(TodoTable.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(TodoTable.COLUMN_SUMMARY)));
            mBodyText.setText(cursor.getString(cursor
                    .getColumnIndexOrThrow(TodoTable.COLUMN_DESCRIPTION)));

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

    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveState();
        outState.putParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
    }

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

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

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

        ContentValues values = new ContentValues();
        values.put(TodoTable.COLUMN_CATEGORY, category);
        values.put(TodoTable.COLUMN_SUMMARY, summary);
        values.put(TodoTable.COLUMN_DESCRIPTION, description);

        if (todoUri == null) {
            // New todo
            todoUri = getContentResolver().insert(
                    MyTodoContentProvider.CONTENT_URI, values);
        } else {
            // Update todo
            getContentResolver().update(todoUri, values, null, null);
        }
    }

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

MyTodoContentProvider

public class MyTodoContentProvider extends ContentProvider{

    //database
    private TodoDatabaseHelper database;

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


    private static final String AUTHORITY =  "com.example.todos.contentprovider";
    private static final String BASE_PATH = "todos";
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY+ "/" + BASE_PATH);

    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +"/todos";

    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/todo";

     private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        sURIMatcher.addURI(AUTHORITY, BASE_PATH, TODOS);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", TODO_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
        queryBuilder.setTables(TodoTable.TABLE_TODO);

        int uriType = sURIMatcher.match(uri);
        switch (uriType) {
        case TODOS:
            break;

        case TODO_ID:
             // adding the ID to the original query
             queryBuilder.appendWhere(TodoTable.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();
         long id = 0;
         switch (uriType) {
        case TODOS:
            id =  sqlDB.insert(TodoTable.TABLE_TODO, null, values);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }
         getContext().getContentResolver().notifyChange(uri, null);
          return Uri.parse(BASE_PATH + "/" + id);
     }

     @Override
     public int delete(Uri uri, String selection,String[] selectionArgs)
     {
         int uriType = sURIMatcher.match(uri);
         SQLiteDatabase sqlDB  = database.getWritableDatabase();
         int rowsDeleted = 0;
         switch (uriType) {

        case TODOS:
            rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO,selection, selectionArgs);
            break;

        case TODO_ID:
            String id = uri.getLastPathSegment();
            if(TextUtils.isEmpty(selection))
            {
                rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO,TodoTable.COLUMN_ID + "=" + id,null);
            }
            else
            {
                rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO,TodoTable.COLUMN_ID + "=" + id + "and" + selection ,selectionArgs);
            }

        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;
         switch (uriType) {
        case TODOS:
            rowsUpdated = sqlDb.update(TodoTable.TABLE_TODO, values, selection, selectionArgs);
            break;
        case TODO_ID:
            String id = uri.getLastPathSegment();
            if(TextUtils.isEmpty(selection))
            {
                rowsUpdated = sqlDb.update(TodoTable.TABLE_TODO, values, TodoTable.COLUMN_ID + "=" +  id, null);
            }
            else
            {
                rowsUpdated = sqlDb.update(TodoTable.TABLE_TODO, 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)
     {
         String[] available = {TodoTable.COLUMN_CATEGORY,TodoTable.COLUMN_SUMMARY,TodoTable.COLUMN_DESCRIPTION,TodoTable.COLUMN_ID};
         HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
         HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
         if(projection != null)
         {
             if (!availableColumns.containsAll(requestedColumns)) {
                throw new IllegalArgumentException("Unknown columns in projection");
              }
         }

     }
}

TodoDatabaseHelper

public class TodoDatabaseHelper extends SQLiteOpenHelper{

    private static final String DATABASE_NAME = "todotable.db";
    private static final int DATABASE_VERSION = 1;


    public TodoDatabaseHelper(Context context)
    {
        super(context,DATABASE_NAME,null,DATABASE_VERSION);
    }

    //Method is called during creation of database
    @Override
    public void onCreate(SQLiteDatabase database)
    {
        TodoTable.onCreate(database);
    }

    // Method is called during an upgrade of the database,
      // e.g. if you increase the database version
      @Override
      public void onUpgrade(SQLiteDatabase database, int oldVersion,
          int newVersion) {
        TodoTable.onUpgrade(database, oldVersion, newVersion);
      }


}

Ответ 1

Вы используете

private static final String AUTHORITY =  "com.example.todos.contentprovider";
// It should same as you defined in manifest

Итак, это

Caused by: java.lang.IllegalArgumentException: Unknown URL content://com.example.todos.contentprovider/todos 

Поэтому убедитесь, что вы определили ContentProvider с тем же authority в manifest.xml

<provider
       android:authorities="com.example.todos.contentprovider"
       android:name=".YOUR_ContentProvider" >
</provider> 

Надеюсь, это сработает для вас.

Ответ 2

Также убедитесь, что вы предоставили андроид: exported = "true" в manifest.xml, также убедитесь, что они помещены внутри </application> не внутри </activity>.

<provider
        android:name="com.example.todos.contentprovider"
        android:authorities="com.example.todos.contentprovider.MyTodoContentProvider"
        android:exported="true">
    </provider>