【发布时间】:2012-02-18 07:33:44
【问题描述】:
我有一个应用程序使用包含在应用程序包中的服务。
我现在正在制作一个新应用,它使用相同服务的更新版本,捆绑在自己的应用程序包中。
如果设备上只安装了一个应用程序,这可以正常工作。但是,如果这两个应用程序都安装在设备上,它们都使用最近安装最少的软件包中的服务——即最旧的软件包。这是有问题的,原因有两个: 1)旧服务不处理新调用(显然) 2) 当使用与其他应用捆绑的服务时,服务最终会使用其他应用保存的数据,而不是自己的。
短期内,我真的只是希望每个应用程序都与自己的服务版本对话。是否可以在不让每个捆绑的服务响应一个独特的意图并让每个应用使用该独特的意图的情况下做到这一点?
从长远来看,最好让两个应用程序都与最新版本的服务通信,让它们共享数据,并且在任一应用程序被卸载时都能正常运行。这样做的正确方法是什么?数据主要存储在 SQLite 数据库中,该数据库存储在Context.getDatabasePath() 指定的位置,这当然是特定于应用程序的,如果卸载该应用程序,该数据库将被擦除。
这是我迄今为止尝试过的:
我可以使用PackageManager.queryIntentServices() 来获取包含两个版本的服务的 ResolveInfo 列表。通过查看ResolveInfo.serviceInfo.applicationInfo.packageName,我可以分辨出哪个是哪个。但是,似乎没有任何方法可以使用该 ResolveInfo 来指定我要处理意图的两个服务中的哪一个。
这似乎应该做正确的事:
serviceIntent.setPackage(context.getApplicationContext().getApplicationInfo().packageName);
因为该 packageName 与我要匹配的那个相同。事实上,当我用修改后的意图调用queryIntentServices 时,我得到一个列表,其中仅包含我的包中的服务。但是,当我尝试使用该意图绑定服务时,它会引发安全异常。
java.lang.RuntimeException: Unable to bind to service my.service.package.name.MyServiceClass@40531558 with Intent { act=my.intent.string pkg=my.app.package.name }: java.lang.SecurityException: Not allowed to start service Intent { act=RuntimeException: Unable to bind to service my.service.package.name.MyServiceClass } without permission private to package
基于一些谷歌搜索,我还尝试通过以下方式创建意图:
Intent serviceIntent = new Intent().setClassName(
"my.service.package.name",
"my.service.package.name.ServiceClassName");
这根本不解决任何服务。
我还尝试将 AndroidManifest.xml 中服务条目中的 android:exported= 更改为 true、false 或未指定,在两个应用程序中以各种组合方式进行更改,但无济于事。 (我希望如果我将它们都设置为 false,那么每个应用程序将只能看到自己的服务副本。)
【问题讨论】:
-
我意识到上述尝试之一存在问题。对于
Intent.setClassName()方法,它应该是:serviceIntent = new Intent().setClassName( context.getApplicationContext().getApplicationInfo().packageName, "my.service.package.name.ServiceClassName");解析为一个服务,正确的一个,但尝试绑定该服务会引发与使用Intent.setPackage()相同的安全异常。
标签: android android-intent android-service