2013-01-16 46 views
6

我已經創建了一個自定義內容提供者,它將被更多的幾個應用程序訪問。我在我的提供程序AndroidManifest.xml文件中包含權限TAG,而在第二個應用程序中,我包含了使用權限標記,但沒有成功。 Logcat顯示我:權限拒絕:開放供應商

java.lang.SecurityException: Permission Denial: opening provider com.company.contentprovider.AplicacaoContentProvider requires READ_DATABASE or WRITE_DATABASE. 

我已經搜索類似的問題,但似乎一切都是正確的。有任何想法嗎 ? 謝謝!

這裏是我的供應商AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.company.contentprovider" 
android:versionCode="1" 
android:versionName="1.0" > 

<uses-sdk 
    android:minSdkVersion="8" 
    android:targetSdkVersion="17" /> 
<permission android:name="READ_DATABASE" android:label="@string/app_read"  android:protectionLevel="normal"></permission> 
<permission android:name="WRITE_DATABASE" android:label="@string/app_write" android:protectionLevel="normal"></permission> 

<application 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme" > 
    <activity 
     android:name=".CompanyProvider" 
     android:label="@string/app_name" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
    <provider android:name="AplicacaoContentProvider" 
     android:authorities="com.company.contentprovider" 
     android:exported="true" 
     android:readPermission="@string/app_read" 
     android:writePermission="@string/app_write" 
     /> 
</application> 

這是我的第二個應用程序的AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.example.testeprovider" 
android:versionCode="1" 
android:versionName="1.0" > 

<uses-sdk 
    android:minSdkVersion="8" 
    android:targetSdkVersion="16" /> 
<uses-permission android:name="android.permissions.READ_DATABASE"/> 
<uses-permission android:name="android.permissioms.WRITE_DATABASE"/> 


<application 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme" > 
    <activity 
     android:name="com.example.testeprovider.MainActivity" 
     android:label="@string/app_name" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

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

</application> 

回答

14

但似乎一切都是正確的

不完全是。

<permission android:name="READ_DATABASE" android:label="@string/app_read"  android:protectionLevel="normal"></permission> 
<permission android:name="WRITE_DATABASE" android:label="@string/app_write" android:protectionLevel="normal"></permission> 

首先,你真的真的真的真的真的真的應該把命名空間上的權限名稱。製作他們com.company.contentprovider.READ_DATABASEcom.company.contentprovider.WRITE_DATABASE

<provider android:name="AplicacaoContentProvider" 
    android:authorities="com.company.contentprovider" 
    android:exported="true" 
    android:readPermission="@string/app_read" 
    android:writePermission="@string/app_write" 
    /> 

其次,你的android:readPermissionandroid:writePermission值需要從<permission>,不android:label使用android:name值。 android:label只是一個顯示名稱。所以,上面的代碼應該是:

<provider android:name="AplicacaoContentProvider" 
    android:authorities="com.company.contentprovider" 
    android:exported="true" 
    android:readPermission="com.company.contentprovider.READ_DATABASE" 
    android:writePermission="com.company.contentprovider.WRITE_DATABASE" 
    /> 

(雖然,獎勵積分明確地把android:exported="true",這是一個好主意)

<uses-permission android:name="android.permissions.READ_DATABASE"/> 
<uses-permission android:name="android.permissioms.WRITE_DATABASE"/> 

三,你的其他清單不使用舊android:name,也不是我建議修改的android:name,也不是android:label,但完全是其他的東西,你選擇說這些在android.permission命名空間,而他們不是。這應該是:

<uses-permission android:name="com.company.contentprovider.READ_DATABASE"/> 
<uses-permission android:name="com.company.contentprovider.WRITE_DATABASE"/> 

(雖然它可能com.company.contentprovider.WRITE_DATABASE就足夠了 - 我不知道,如果android:writePermission將自動意味着android:readPermission與否)

讓這些變化,我想你會有更好的運氣。

+0

謝謝!我明天開始工作,我會做出這些修改並讓你知道結果! –

+0

它的工作方式,就像你說的那樣,但還有另一個疑問。比方說,我有20多個可以訪問我的內容提供商的應用程序。我希望每個應用都檢查內容提供者是否存在。如果是這樣,那麼就使用權限來記錄數據。否則,註冊提供商並記錄數據。所以,我想在每個應用程序的AndroidManifest.xml文件中包含權限和使用權限標籤。它會工作嗎? youtube downloader

+0

@MauricioAlencar:「我想我的應用程序中的每一個檢查,如果內容提供商存在,如果是的話,那麼就。使用許可來記錄數據,否則,註冊提供商並記錄數據一個。」 - 這是一個非常糟糕的計劃。請讓所有20個應用程序完全獨立。就目前而言,您的計劃表示,如果用戶恰好卸載了20箇中的1個,而1個恰好是決定成爲ContentProvider的1個,則他們會丟失所有20個應用程序的數據。 – CommonsWare

13

上面的答案對我來說是個棘手的問題。但我現在明白了。我也想發佈我的解決方案。也許對某人來說,理解起來會更好。

第一個應用程序A是具有SQLite數據庫和「自定義內容提供者」的應用程序。應用B與ContentResolver一起使用來自App A的數據庫。

這是AndroidManifest。從應用程序一個XML的文件:

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

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


<permission android:name="de.test.READ_DATABASE" android:protectionLevel="normal" /> 
<permission android:name="de.test.WRITE_DATABASE" android:protectionLevel="normal" /> 

<application 
    android:debuggable="true" 
    ... > 
    ... 
    ... 
    <provider 
     android:name="de.test.TestContentProvider" 
     android:authorities="de.test.ContentProvider" 
     android:exported="true" 
     android:readPermission="de.test.READ_DATABASE" 
     android:writePermission="de.test.WRITE_DATABASE" /> 
    ... 
    ... 
</application> 

好吧,這是從應用程序B.重要的AndroidManifest.xml中,文件與 「使用許可權」 的一部分:

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

<uses-sdk 
    android:minSdkVersion="15" 
    android:targetSdkVersion="17" /> 

<uses-permission android:name="de.test.READ_DATABASE" /> 
<uses-permission android:name="de.test.WRITE_DATABASE" /> 

<application 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme" > 
    <activity 
     android:name="de.test.testercontentprovider.MainActivity" 
     android:label="@string/app_name" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 

而且ContentProvider的對應用程序A中的代碼如下所示:

public class TestContentProvider extends ContentProvider { 

public static final String AUTHORITY = "de.test.TestContentProvider"; 

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY 
     + "/" + "nameoftable"); 


@Override 
public boolean onCreate() { 
    ... 
    return true; 
} 

@Override 
public Cursor query(Uri uri, String[] projection, String selection, 
     String[] selectionArgs, String sortOrder) { 
    // TODO Auto-generated method stub 
      return null; 
} 

@Override 
public int update(Uri uri, ContentValues values, String selection, 
     String[] selectionArgs) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public int delete(Uri uri, String selection, String[] selectionArgs) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public Uri insert(Uri uri, ContentValues values) { 
    // TODO Auto-generated method stub 
    return null; 
} 

@Override 
public String getType(Uri uri) { 
    // TODO Auto-generated method stub 
    return null; 
} 
} 

,代碼爲ContentResolver的從應用B:

public class MainActivity extends Activity { 

private static final String TAG = MainActivity.class.getSimpleName(); 
public static final String AUTHORITY = "de.test.TestContentProvider"; 
public static final String TABLE_NAME = "nameoftable"; 

    ... 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    ContentResolver cr = getContentResolver(); 

    // show entries of db 
    listEntries(cr); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

private void listEntries(ContentResolver cr) { 
    Uri uri = Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME); 
    Cursor c = cr.query(uri, null, null, null, null); 

    if (c == null) { 
     Log.d(TAG, "Cursor c == null."); 
     return; 
    } 
    while (c.moveToNext()) { 
     String column1 = c.getString(0); 
     String column2 = c.getString(1); 
     String column3 = c.getString(2); 

     Log.d(TAG, "column1=" + column1 + " column2=" + column2 + " column3=" + column3); 
    } 
    c.close(); 
} 
} 

我希望這可以幫助別人更好地理解它。

+0

更清晰! –

+0

非常有幫助謝謝! – rufism

-2
public static final String AUTHORITY = "de.test.TestContentProvider"; 
//...... 

有一個問題,是否應該

android:authorities="de.test.ContentProvider" 
<--- 
相關問題