【问题标题】:How to start android service from another Android app如何从另一个 Android 应用程序启动 android 服务
【发布时间】:2013-06-26 09:24:39
【问题描述】:

我在从另一个 Android 应用 (API 17) 启动服务时遇到问题。 但是,如果我确实从 shell 运行 'am',则服务可以正常启动。

# am startservice com.xxx.yyy/.SyncService
Starting service: Intent { act=android.intent.action.MAIN cat=
[android.intent.category.LAUNCHER] cmp=com.xxx.yyy/.SyncService }
(service starts fine at this point)
# am to-intent-uri com.xxx.yyy/.SyncService
intent:#Intent;action=android.intent.action.MAIN;
category=android.intent.category.LAUNCHER;
component=com.xxx.yyy/.SyncService;end

所以,当我在代码中执行相同操作时,看起来我没有遗漏任何意图:

Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setComponent(new ComponentName("com.xxx.yyy", ".SyncService"));
ComponentName c = ctx.startService(i);
if (c == null) { Log.e(TAG, "failed to start with "+i); }

我得到的是(当时服务没有运行):

E/tag( 4026): failed to start with Intent { 
act=android.intent.action.MAIN 
cat=[android.intent.category.LAUNCHER] 
cmp=com.xxx.yyy/.SyncService }

我在服务上没有意图过滤器,我不想设置一个,我真的想了解我在通过其组件名称启动它时做错了什么,或者可能会造成什么这是不可能的。

【问题讨论】:

  • @Richa 此页面有使用 Intent.setClassName() 的示例,但它并没有真正回答我的具体问题...
  • 另外,检查 logcat 是否有任何有意义的错误(不要过滤 logcat,因为您可能会错过一些有价值/重要的东西)

标签: android android-intent


【解决方案1】:

您应该能够像这样启动您的服务:

Intent i = new Intent();
i.setComponent(new ComponentName("com.xxx.yyy", "com.xxx.yyy.SyncService"));
ComponentName c = ctx.startService(i);

如果您指定特定组件,则无需设置 ACTION 或 CATEGORY。确保您的服务在清单中正确定义。

【讨论】:

  • 嗨,i.setComponent(new ComponentName("com.xxx.yyy", ".SyncService")); 不起作用。只有完全限定的名称有效 i.setComponent(new ComponentName("com.xxx.yyy", "com.xxx.yyy.SyncService")); ,请更新。
  • 补充一下,如果应用和服务在不同的包中,代码应该是 i.setComponent(new ComponentName("app.package", "service.package"));
  • @Vinayaka 实际上没有。 new ComponentName() 的第一个参数是Service 的包名,第二个参数是Service 的全限定类名。
  • 如果我有一个包名称为“abc.123.a”的服务并且应用程序名称为“app.name.full”怎么办。 ComponentName("app.full.name", "abc.123.a") 正确吗??
  • @HansBrende 抱歉,如果我的评论令人困惑。第一个参数是包含Service 的应用的Android 包名。它不是Service 类的Java 包名。您的链接问题也已得到解决,因为似乎 OP 更改了他的包名称导致混淆。我的评论是对 Vinayaka 在 22:00 的评论的回应,其中 service.package 作为第二个参数是不正确的。
【解决方案2】:

像这样开始你的服务

Intent intent = new Intent();
intent.setComponent(new ComponentName("pkg", "cls"));
ComponentName c = getApplicationContext().startForegroundService(intent);

顺便说一句,您实际上需要使用 applicationId,而不是 pkg。它可以在应用程序 gradle 中找到。我为这个错误苦苦挣扎了好几个小时!

   defaultConfig {
        applicationId "com.xxx.zzz"
}

cls 是清单中声明的​​服务的名称。例如:com.xxx.yyy.yourService。

 <service android:name="com.xxx.yyy.yourService"
android:exported="true"/>

【讨论】:

  • 你和我都是,伙计。谢谢!
【解决方案3】:

作为对 David Wasser 的回答的补充,以使其在以 API 30 及更高版本为目标时工作,您还必须添加:

清单中查询标记中的必需包名称:

<queries>
        <package android:name="com.example.service.owner.app" />
</queries>

或许可

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

Additional info on package visibility changes here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多