web-dev-qa-db-ja.com

android)からサービスを開始する際の権限の問題

アプリケーションの一部としてサービスを作成しました。次のコードを使用して、2番目のアプリケーションからこのサービスを呼び出そうとします。

    Intent intent = new Intent () ;
    intent.setClassName("com.test" ,"com.test.DownloadService") ;
    // Create a new Messenger for the communication back
    Messenger messenger = new Messenger(handler);
    intent.putExtra("MESSENGER", messenger);
    intent.setData(Uri.parse("http://www.vogella.com/index.html"));
    intent.putExtra("urlpath", "http://www.vogella.com/index.html");
    this.startService(intent);

次の例外があります

07-10 09:27:28.819: ERROR/AndroidRuntime(4226): FATAL EXCEPTION: main
    Java.lang.RuntimeException: Unable to start activity ComponentInfo{com.inject/com.inject.MyActivity}: Java.lang.SecurityException: Not allowed to start service Intent { dat=http://www.vogella.com/index.html cmp=com.test/.DownloadService (has extras) } without permission not exported from uid 10109
    at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:1971)
    at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:1996)
    at Android.app.ActivityThread.access$700(ActivityThread.Java:126)
    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1156)
    at Android.os.Handler.dispatchMessage(Handler.Java:99)
    at Android.os.Looper.loop(Looper.Java:137)
    at Android.app.ActivityThread.main(ActivityThread.Java:4458)
    at Java.lang.reflect.Method.invokeNative(Native Method)
    at Java.lang.reflect.Method.invoke(Method.Java:511)
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:784)
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:551)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: Java.lang.SecurityException: Not allowed to start service Intent { dat=http://www.vogella.com/index.html cmp=com.test/.DownloadService (has extras) } without permission not exported from uid 10109
    at Android.app.ContextImpl.startService(ContextImpl.Java:1122)
    at Android.content.ContextWrapper.startService(ContextWrapper.Java:359)
    at com.inject.MyActivity.onCreate(MyActivity.Java:28)
    at Android.app.Activity.performCreate(Activity.Java:4465)
    at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1049)
    at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:1935)
    ... 11 more

この権限の問題が発生するのはなぜですか?

同じアプリからサービスを呼び出すと、次のコードが完全に機能します。

    Intent intent = new Intent(this, DownloadService.class);
    // Create a new Messenger for the communication back
    Messenger messenger = new Messenger(handler);
    intent.putExtra("MESSENGER", messenger);
    intent.setData(Uri.parse("http://www.vogella.com/index.html"));
    intent.putExtra("urlpath", "http://www.vogella.com/index.html");
    startService(intent);

App2のマニフェストで必要なすべてのアクセス許可を付与しましたが、別のアプリケーションからサービスを呼び出すときにこのアクセス許可の問題が発生する理由を誰かに教えてもらえますか。

[〜#〜]編集[〜#〜]

App2のマニフェスト

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
      package="com.inject"
      Android:versionCode="1"
      Android:versionName="1.0">
<uses-sdk Android:minSdkVersion="14"/>
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
<application Android:label="@string/app_name" Android:icon="@drawable/ic_launcher">
    <activity Android:name="MyActivity"
              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>
</manifest>

サービスを含むApp1のマニフェスト

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
      package="com.test"
      Android:versionCode="1"
      Android:versionName="1.0">
<uses-sdk Android:minSdkVersion="14"/>
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
        Android:icon="@drawable/ic_launcher"
        Android:label="@string/app_name" >
    <activity
            Android:name=".MainActivity"
            Android:label="@string/app_name" >
        <intent-filter>
            <action Android:name="Android.intent.action.MAIN" />


        </intent-filter>
    </activity>

    <service Android:name="DownloadService" >
    </service>
</application>
</manifest>
14
user1400538

このサービスは、明示的に利用可能にしていないため、他のアプリケーションでは利用できません。サービスは次のように定義する必要があります。

<service Android:name="DownloadService"
         Android:exported="true">
</service>

追加の権限は必要ありません(使用する場合を除く)

16
David Wasser

ドキュメント を読んだことがありますか?この問題は非常に明確です。

サービスへのグローバルアクセスは、マニフェストのタグで宣言されたときに強制できます。そうすることで、他のアプリケーションは、サービスを開始、停止、またはバインドできるように、独自のマニフェストで対応する要素を宣言する必要があります。

Gingerbreadの時点で、Context.startService(Intent)を使用する場合、Intent.FLAG_GRANT_READ_URI_PERMISSIONまたはIntent.FLAG_GRANT_WRITE_URI_PERMISSION、あるいはその両方をインテントに設定することもできます。これにより、サービスはインテント内の特定のURIへの一時的なアクセスを許可されます。アクセスは、サービスがその開始コマンドまたはそれ以降のコマンドに対してstopSelf(int)を呼び出すまで、またはサービスが完全に停止されるまで維持されます。これは、サービスを保護する権限を要求していない他のアプリへのアクセスを許可する場合、またはサービスがまったくエクスポートされていない場合でも機能します。

さらに、サービスは、その呼び出しの実装を実行する前にcheckCallingPermission(String)メソッドを呼び出すことにより、アクセス許可を使用してサービスへの個々のIPC呼び出しを保護できます。

一般的なアクセス許可とセキュリティの詳細については、セキュリティとアクセス許可のドキュメントを参照してください。

ドキュメントを読んだ後も権限の問題が解決しない場合は、AndroidManifest.xmlをお知らせください。マニフェストのサービスの exportedおよびpermission 属性も参照してください。

2
theomega