在两个应用程序之间进行通信的最佳方式

时间:2018-06-13 06:18:36

标签: android

我想为一套应用程序创建一个中央应用程序。这套应用程序由我们自己和第三方供应商开发。我们想知道实现以下功能的最佳方法

1)从中央应用程序启动子应用程序

子应用程序安装在设备中,子应用程序的包名称由供应商提供。我们考虑使用显式意图来调用子应用程序。从中央应用程序启动子应用程序的任何其他方法。

2)中央和子应用程序之间的通信。

子应用程序没有通信层。来自子应用程序的每个通信都应通过中央应用程序发送到服务器。通信包括GET,POST,PUT请求。我们考虑使用Broad Cast接收器将有效载荷发送到中央应用程序。中央应用程序将依次将有效负载发送到服务器。但广播接收器对Android Oreo的限制将使这种解决方案不可行。

3)当用户在中央应用程序中执行注销时,关闭从中央应用程序启动的子应用程序。

我们正在考虑使用作为ActivityManager一部分提供的killBackgroundProcesses()API来终止进程。杀死进程的任何其他解决方案?使用此API杀死进程会产生任何负面影响吗?

4)将中央应用程序中的事件发布到要使用的子应用程序。

我们想到广播接收器从中央到子应用程序发布事件。但如上所述,Android Oreo上的广播接收器限制将使这种解决方案不可行。任何替代解决方案?

5 个答案:

答案 0 :(得分:1)

您需要的是Implicit Intents。这样,您的子应用程序无需从中央应用程序中了解实施细节。

只需使用您的中央应用程序将其理解为命令的特定动作常量创建意图。然后,中央应用程序决定要完成的REST操作。 (我建议您的每个子应用程序和中央应用程序都包含相同的库模块(实际上是SDK),其中将包含常量)

 //in this example ActionConstants would just be a class with
 //some string constants
 Intent intent = new Intent(ActionConstants.UPDATE_NAME);
 intent.putExtra(ActionConstants.EXTRA_NAME, myNewName);

 public final class ActionConstants {

     public static final String UPDATE_NAME = "com.my.example.app.UPDATE_NAME";

     private ActionConstants(){}

 }

您的应用程序大概是单独的APK,这意味着您可能要在发送Intent之前检查是否已安装Central应用程序-这样可以防止子应用程序崩溃,并让您有机会向用户显示对话框(等),他们无法完成操作。

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    //You can use startBroadcast, or start activity with no UI
    startActivity(intent);
} else {
    Log.d(TAG, "Intent not sent");
    //Notify user
}

然后在中央应用程序中,您要接收意图并对其进行处理:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    String action = intent.getAction();
    switch(action) {
        case ActionConstants.UPDATE_NAME:
            if (intent.hasExtra(ActionConstants.EXTRA_NAME)) {
                //TODO: Now you contact the server and carry out your update
            } else {
                //No name supplied, it's an error, maybe broadcast the error back to sub app
            }
            break;
    }
}

要使中央应用程序实际接收到明确的意图,必须在清单中注册活动和过滤器:

<activity android:name="MyActivity">
    <intent-filter>
        <!-- Note that the action matches the constant we used -->
        <action android:name="com.my.example.app.UPDATE_NAME"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>
  

我们考虑过使用Broad广播接收器将有效载荷发送到中央应用程序。 Android Oreo上的广播接收器限制将使该解决方案不可行

不用担心。使用中央应用程序中的JobScheduler甚至是前台服务,您仍然可以实时进行通信,但是隐式意图是一个更好的选择

  

我们正在考虑使用killBackgroundProcesses

这不是一个干净的方法,而是对意图使用另一个操作,当子应用程序收到意图时,它就可以完成

  

我们认为广播接收器可以将事件从中央发布到子应用程序

同样,一种解决方法是让每个子应用程序运行一个服务,该服务在上下文中注册BC-这可以在您的库模块中,因此每个子应用程序都可以运行它-但这根本不是一个干净的解决方案。这仅在子应用程序需要在后台接收广播时才重要。一种替代方法是使用子应用打开时可以使用的即时广播。

一个最终的想法-应用之间交互的一种稍微复杂的解决方案是让每个子应用向中央应用发送一个意图,该意图包含一个明确广播接收者的字符串常量(在子应用清单中声明)。然后,中央应用程序将此事件视为注册事件,并保留所有子应用程序的列表,以便在发送广播时明确联系。 (这只是意味着将广播循环发送到每个子应用程序中)

答案 1 :(得分:0)

回答具体问题,而不是你的实施是否合适,奥利奥的明确广播意图和接收者都不受影响,所以应该工作。

Differentiate implicit broadcast receiver vs explicit broadcast receiver in the manifest

答案 2 :(得分:0)

1使用Intents最适合调用子应用程序。

2对于应用程序之间的通信存在AIDL虽然它可能看起来有点难以实现但实际上它很容易通过在应用程序之间提供非常基本的接口为您提供在android中进行进程间通信的方法。 Google Play服务使用此功能执行In App Payments。

3您应该使用帐户管理器,这将有助于在整个应用程序套件中共享相同的访问令牌,并将优雅地处理登录和注销功能。

4这再次使用AIDL完成。

我还觉得你应该重新审视这个解决方案的架构,因为你的所有工作似乎都可以在一个应用程序中完成,而且似乎没有用来创建这样精细的应用程序设计。

答案 3 :(得分:0)

1)

Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
if (launchIntent != null) { 
    startActivity(launchIntent);//null pointer check in case package name was not found
}

 2)尝试看一下内容提供商 https://developer.android.com/guide/topics/providers/content-provider-basics

答案 4 :(得分:0)

最好实现像CometD这样的消息传递库。如果要从中央应用程序控制和监视客户端应用程序和用户的活动。我们可以使用客户端应用程序状态(例如用户会话处于活动状态,非活动状态,超时,阻止或取消阻止)并发送信息(例如推送通知,消息等)。一切都可以通过commetD完成。