从android启动服务时的权限问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11410718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:18:49  来源:igfitidea点击:

Permission issue while starting a service from android

androidandroid-intentandroid-serviceandroid-permissions

提问by user1400538

I have written a service as part of an application. I try to call this service from a second application using the following code:

我编写了一个服务作为应用程序的一部分。我尝试使用以下代码从第二个应用程序调用此服务:

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

It gives the following exception

它给出了以下异常

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.access0(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

Why this permission issue occurs?

为什么会出现这个权限问题?

The following code works perfect when I call the service from the same app:

当我从同一个应用程序调用服务时,以下代码完美运行:

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

Can someone please let me know why I get this permission issue when I call the service from a different application, though I have given all the required permissions in App2's manifest.

尽管我已经在 App2 的清单中提供了所有必需的权限,但有人可以告诉我为什么当我从不同的应用程序调用该服务时会出现此权限问题。

EDIT

编辑

Manifest of 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>

Manifest of App1 which contains the service

包含服务的 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>

回答by David Wasser

The service isn't available to other applications because you haven't made it explicitly available. Your service needs to be defined like this:

该服务对其他应用程序不可用,因为您尚未明确使其可用。您的服务需要像这样定义:

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

You don't need any extra permissions (unless you want to use them)

您不需要任何额外的权限(除非您想使用它们)

回答by theomega

Have your read the documentation? It is quite clear with this issue:

你读过文档吗?这个问题很清楚:

Global access to a service can be enforced when it is declared in its manifest's tag. By doing so, other applications will need to declare a corresponding element in their own manifest to be able to start, stop, or bind to the service.

As of GINGERBREAD, when using Context.startService(Intent), you can also set Intent.FLAG_GRANT_READ_URI_PERMISSION and/or Intent.FLAG_GRANT_WRITE_URI_PERMISSION on the Intent. This will grant the Service temporary access to the specific URIs in the Intent. Access will remain until the Service has called stopSelf(int) for that start command or a later one, or until the Service has been completely stopped. This works for granting access to the other apps that have not requested the permission protecting the Service, or even when the Service is not exported at all.

In addition, a service can protect individual IPC calls into it with permissions, by calling the checkCallingPermission(String) method before executing the implementation of that call.

See the Security and Permissions document for more information on permissions and security in general.

当服务在其清单的标签中声明时,可以强制执行对服务的全局访问。通过这样做,其他应用程序将需要在自己的清单中声明相应的元素才能启动、停止或绑定到服务。

从 GINGERBREAD 开始,当使用 Context.startService(Intent) 时,您还可以在 Intent 上设置 Intent.FLAG_GRANT_READ_URI_PERMISSION 和/或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这将授予服务对 Intent 中特定 URI 的临时访问权限。访问将一直保持,直到服务为该启动命令或后续命令调用 stopSelf(int),或者直到服务完全停止。这适用于授予对未请求保护服务的权限的其他应用程序的访问权限,或者甚至在根本没有导出服务的情况下。

此外,通过在执行该调用的实现之前调用 checkCallingPermission(String) 方法,服务可以使用权限保护单个 IPC 调用。

有关一般权限和安全性的更多信息,请参阅安全和权限文档。

Show us your AndroidManifest.xmlif you still have permission problems after reading the documentation. Also see the exportedand the permissionattribute of the service in your manifest.

AndroidManifest.xml如果您在阅读文档后仍有权限问题,请向我们展示您的信息。另请参阅清单中服务的exportedpermission属性。