【问题标题】:Starting a service of another Android app into my own app在我自己的应用程序中启动另一个 Android 应用程序的服务
【发布时间】:2023-03-28 03:21:01
【问题描述】:

我正在使用 am startservice 从 shell 运行 android 应用程序的服务。一切正常。

am startservice -a com.anotherdeveloper.app.SERVICE --ef a 1 --ef b 2

我想知道是否可以在不作为开发人员的情况下启动另一个 android 应用程序的服务? 根据此链接,有可能: How to start android service from another Android app

但我不太明白该怎么做。

这是我在MainActivity 中使用的代码:

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.anotherdeveloper.app", "com.anotherdeveloper.app.SERVICE"));
ComponentName c = getApplicationContext().startForegroundService(intent);

我在AndroidManifest.xml 中添加了这个:

  <service
        android:name="com.anotherdeveloper.app.SERVICE"
        android:enabled="true"
        android:exported="true" />

但它在清单中显示一个错误,因为 Android Studio 无法找到我手机上安装的此应用程序的包名称。


更新

感谢@Martin Marconcini,这是我正在使用的代码:

  Intent intent = new Intent();
  intent.setComponent(new ComponentName("com.anotherdeveloper.app","com.anotherdeveloper.app.SERVICE"));
  intent.putExtra("cty", 4);
  intent.putExtra("stt", 2);
  startService(intent);

这是AndroidManifest.xml中的服务:

<service name="com.anotherdeveloper.app.General">
  <intent-filter>
    <action name="com.anotherdeveloper.app.SERVICE"/>
  </intent-filter>
  <intent-filter>
    <action name="com.anotherdeveloper.app.SERVICE_ALT"/>
  </intent-filter>
  <intent-filter>
    <action name="com.anotherdeveloper.app.TERMINATE"/>
  </intent-filter>
</service>

【问题讨论】:

    标签: java android android-studio android-intent android-service


    【解决方案1】:

    简短回答:这完全取决于第 3 方的决定(服务创建者在相应的android:exported 中写了什么)

    更多详情:https://developer.android.com/guide/topics/manifest/service-element

    【讨论】:

    • 既然我可以从 shell 启动服务,那是否意味着android:exported 的值是true,因此该服务是供外部使用的?
    • 是的,如果你可以在命令行中启动它,你可以在你的代码中使用它但是你确定你可以在命令行中启动它吗?您的代码将其作为前台服务启动(正确),但您的命令行没有。我不认为你的命令行(它被指定的方式)应该工作。
    • 一个例子:am start-foreground-service com.anotherdeveloper.app/.SERVICE
    • 是的,我已经在命令行中尝试过了,它可以工作。那么也许问题是我不应该将它作为前台服务启动?另外,我应该在 manifest.xml 中添加什么,因为它在android:name="com.anotherdeveloper.app.SERVICE" 上给我一个错误?
    • 您不应更改应用的清单以调用 3rd 方服务。但是我不确定“不作为前台启动” - 这取决于您的设备 sdk 版本(startForegroundService 要求 min sdk 为 26,所以如果您的设备说 21 它将无法工作)
    【解决方案2】:

    在 cmets 中扩展您的问题:

    1. 是的,如果服务已导出(并且您说是),您可以启动该服务,所以它应该可以工作。

    2. 要通过 Intent 传递参数,您需要使用“Extras”。这类似于您在adb shell am 中使用的-e 参数。

    Intent i = new Intent();
    i.putXXX(key, value)
    

    您将获得很多选项(针对每种类型)而不是 XXX ,例如:

    int value = 1;
    i.putExtra("Key", value)
    
    // or
    
    String value = "X"
    i.putExtra("Key", value)
    
    // or
    
    boolean value = true;
    i.putExtra("Key", value)
    

    它们都可以工作(当然要使键独一无二)。

    或者,您可以传递包含一堆的Bundle

            Bundle b = new Bundle();
            b.putString("x", "value");
            b.putInt("x", 1);
            b.putBoolean("x", true);
    
            Intent i = new Intent();
            i.putExtra("theBundle", b);
    

    本质上,这一切都非常类似于 Google/Java,其中一致性不是的关键。 ;)

    (当然,如果你传递一个包,receiver 必须知道这一点,这样它才能从额外内容中“获取包”,然后提取每个键/值。

    换句话说,Bundle 是一个美化的字典,它支持不同的类型,并且所有的东西都必须是Parcelable。所以它是一个必须是可打包的键/值存储。

    Intent 数据大小(用于附加)有 X 的限制(不记得是 1mb 还是什么),但您不能只序列化 1 TB 的信息并通过 Intent 扔掉它。记住这一点。

    【讨论】:

    • 非常感谢您的回答。你能检查更新的问题吗?我添加了代码和一些 AndroidManifest.xml。看来您是对的,该服务中没有exported="true"...这很奇怪,因为我可以从外壳启动服务,这是否意味着该服务是供外部使用的?
    • 问题:您是否尝试将getApplicationContext(). 更改为this.,因为您已经处于 活动/上下文中。这行得通吗?
    • getApplicationContext().startService(intent)this.startService(intent) 都试过了。
    • 嗯好吧,我今天去看看,看看能不能找到什么。在过去的几年里,我并没有真正通过 cmd 线启动很多服务;这是一种通常特定于项目的事情,无论出于何种原因,你都会经常这样做,当你完成后,你就再也不会碰它了。所以我想确保我在这里没有给出不好的建议。
    猜你喜欢
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多