2013-01-16 42 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" 
<--- 
相关问题