2013-01-16 21 views
6

カスタムコンテンツプロバイダを作成しました。これにはさらにいくつかのアプリケーションからアクセスできます。私は、プロバイダのAndroidManifest.xmlファイルにアクセス許可タグを含めました.2番目のアプリケーションでは、使用許可タグが含まれていましたが、成功しませんでした。 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値がないandroid:label<permission>から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名前空間にあると言っていますが、そうではありません。

は、それらの変更を行い、そして私はあなたがすると思います - (android:writePermissionが自動的にandroid:readPermissionを意味かない場合、私は知らない、com.company.contentprovider.WRITE_DATABASEは十分であろうことは可能であるが)

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

:これがなければなりませんより良い運を持っています。

+0

ありがとうべきであるかどうか質問があります!私はすぐに仕事に着きますが、私はこれらの変更を行い、結果についてあなたに知らせます! –

+0

それはあなたの言ったとおりに機能しましたが、別の疑問があります。私は、私のコンテンツプロバイダにアクセスする20以上のアプリケーションを持っています。コンテンツプロバイダが存在するかどうかを各アプリで確認する必要があります。そうであれば、データの記録にパーミッションを使用するだけです。それ以外の場合は、プロバイダを登録してからデータを記録します。ですから、私は、各アプリケーションのAndroidManifest.xmlファイルにpermissionタグとuses-permissionタグの両方を入れるようなものを考えました。それはうまくいくの? youtube downloader

+0

@MauricioAlencar:「私は、コンテンツプロバイダが存在する場合は、私のアプリケーションの一つ一つ確認したいことがない場合、単に。データを記録する権限を使用します。それ以外の場合はプロバイダを登録し、dat a。 "それは非常に悪い計画です。 20のアプリケーションをすべて完全に独立させてください。あなたの計画では、ユーザが20人のうち1人をアンインストールすると、1人が「ContentProvider」に決定した1人になったとすれば、20人すべてのアプリケーションのデータが失われます。 – CommonsWare

13

上記の答えは私には分かりにくいものでした。しかし、私は今それを得た。私は私の解決策も掲載したい。たぶん、誰かのために理解する方がより良いです。

最初のアプリケーションAは、SQLiteデータベースと「カスタムコンテンツプロバイダ」を持つアプリケーションです。 AppBは、ContentResolverと共にAppAのデータベースからデータを使用します。

これはAndroidManifestです。アプリケーションAからの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> 

[OK]を、これが重要なアプリケーション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> 

とアプリAのためのContentProviderのコード

は次のようになります。

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; 
} 
} 
私は、これは、誰かがそれをよりよく理解するのに役立つことを願って

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

とアプリBからContentResolverのためのコード。

+0

はるかに明確です! –

+0

非常に助けてくれてありがとう! – rufism

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

それは

android:authorities="de.test.ContentProvider" 
<--- 
関連する問題