声明内容提供程序

12

这是我第一次使用内容提供程序,但我遵循了开发者文档。当我运行程序时,它告诉我未能找到提供程序信息

以下是我的清单文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tyczj.bowling"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="11" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >

    <activity android:name="Tabs">
        <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
    </activity>

    <activity android:name="BowlersList"></activity>
</application>

<provider android:name="com.tyczj.bowling.BowlersDB"
    android:authorities="com.tyczj.bowling.bowlersdb">
</provider>

</manifest>

还有我的内容提供者。

public class BowlersDB extends ContentProvider {

private static final String DATABASE_NAME = "Bowlers";
private static final String BOWLERS_TABLE = "bowlers_table";
private static final int DATABASE_VERSION = 1;
public static final Uri CONTENT_URI = Uri.parse("content://com.tyczj.bowling.bowlersdb");
private static final UriMatcher uriMatcher;
static final String NAME = "name";
static final String ID = "_id";

private DatabaseHelper DBHelper;
private SQLiteDatabase db;

public Cursor getBowlers(){
    return db.query(BOWLERS_TABLE, new String[] {ID,NAME},null,null,null,null,NAME + " ASC");
}

public Cursor getId(String name){
    Cursor c = db.query(BOWLERS_TABLE, new String[] {ID,NAME},NAME + "='" + name +"'",null,null,null,null);
    if(c != null && c.moveToFirst()){
        do{
            if(c.getString(c.getColumnIndex(NAME)).equals(name)){
                return c;
            }
        }while(c.moveToNext());
    }
    return c;
}

private static class DatabaseHelper extends SQLiteOpenHelper 
{
    DatabaseHelper(Context context) 
    {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) 
    {
        createTables(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, 
                          int newVersion) 
    {
        Log.w("CalendarDB", "Upgrading database from version " + oldVersion 
              + " to "
              + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS Events_Table");
        onCreate(db);
    }

    private void createTables(SQLiteDatabase db){
        db.execSQL("CREATE TABLE " + BOWLERS_TABLE + "(" + ID + " integer primary key autoincrement, " +
                NAME + " TEXT);");
    }
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    int count = 0;
    int num = uriMatcher.match(uri);
    if(num == 1){
        count = db.delete(BOWLERS_TABLE, selection,selectionArgs);
    }else if(num == 2){
        String id = uri.getPathSegments().get(1);
        count = db.delete(BOWLERS_TABLE, ID + " = " + id + (!TextUtils.isEmpty(selection) ? " AND (" + 
                   selection + ')' : ""), 
                   selectionArgs);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return count;
}

@Override
public String getType(Uri uri) {
    if(uriMatcher.match(uri) == 1){
        return "vnd.android.cursor.dir/vnd.tyczj.bowlersdb ";
    }else if(uriMatcher.match(uri) == 2){
        return "vdn.android.cursor.item/vnd.tyczj.bowlersdb ";
    }else
        throw new IllegalArgumentException("Unsupported URI: " + uri);

}

@Override
public Uri insert(Uri uri, ContentValues values) {
    long rowID = db.insert(BOWLERS_TABLE,null, values);
    if(rowID > 0){
        Uri _uri = ContentUris.withAppendedId(CONTENT_URI,rowID);
        getContext().getContentResolver().notifyChange(_uri,null);
        return _uri;
    }else{
        throw new SQLException("Failed to insert row into " + uri);
    }
}

@Override
public boolean onCreate() {
    Context context = getContext();
    DBHelper = new DatabaseHelper(context);
    db = DBHelper.getWritableDatabase();
    return (db == null)? false:true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
    sqlBuilder.setTables(BOWLERS_TABLE);

    if(uriMatcher.match(uri) == 1){
        sqlBuilder.appendWhere(ID + " = " + uri.getPathSegments().get(1));
    }
    if(sortOrder == null || sortOrder == "")
        sortOrder = NAME;
    Cursor c = sqlBuilder.query(db, projection, selection, selectionArgs,null,null, sortOrder);
    c.setNotificationUri(getContext().getContentResolver(), uri);
    return c;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
        String[] selectionArgs) {
    int count = 0;
    int num = uriMatcher.match(uri);
    if(num == 1){
        count = db.update(BOWLERS_TABLE, values, selection, selectionArgs);
    }else if(num == 2){
        count = db.update(BOWLERS_TABLE, values, ID + " = " + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(selection) ? " AND (" + 
                  selection + ')' : ""), 
                  selectionArgs);
    }else{
        throw new IllegalArgumentException(
                "Unknown URI " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return count;
}

static{
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI("com.tyczj.bowling.bowlersdb","bowlers",1);
    uriMatcher.addURI("com.tyczj.bowling.bowlersdb","bowlers/#",2);
}

}

不确定自己做错了什么?

4个回答

21

提供程序需要在应用程序标记中。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tyczj.bowling"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="11" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <activity android:name="Tabs">
            <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
        </activity>

        <activity android:name="BowlersList"></activity>
    <provider android:name="com.tyczj.bowling.BowlersDB"
        android:authorities="com.tyczj.bowling.bowlersdb">
    </provider>
    </application>



</manifest>

好的,我做到了,不再出现“找不到提供程序”的错误,但现在它告诉我“列“_id”不存在”? - tyczj
如果您将提供程序标签放在应用程序标签外部,则在Kit Kat中会失败,但在其他所有地方都可以正常工作...将其放在应用程序标签内部会在KK中崩溃。 - Robert Sherman

3
在ContentProvider的onCreate中不应调用db = DBHelper.getWritableDatabase();。在SQLiteOpenHelper文档中,对于getReadableDatabasegetWritableDatabase的原因给出了解释:

与getWritableDatabase类似,此方法可能需要很长时间才能返回,因此您不应从应用程序主线程中调用它,包括从ContentProvider.onCreate()中调用。

相反,应保持对SQLiteOpenHelper实例的引用,并在查询/插入/删除/更新方法中根据需要调用getWritableDatabase/getReadableDatabase,这些方法在使用Loader时会以异步方式调用。

抱歉,这不是直接针对问题,但我已经在各种代码示例中看到过很多次。


2
你遇到这个错误是因为你在Application标签之外定义了Provider。请将你的Provider定义放在Application标签内部。
<application
       ........

    <provider 
        android:name="com.tyczj.bowling.BowlersDB"
        android:authorities="com.tyczj.bowling.bowlersdb">
    </provider>
    </application>

0
这是一个很好的例子,说明为什么要在Eclipse中使用Android清单编辑器。它将这些项/组件放置在它们的语法正确位置,因此您不需要担心这个问题。 另一种看待它的方式:考虑在开始时(以及偶尔在整个过程中)使用清单编辑器来确认您的清单的正确性。

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