天天看点

Android不同APP之间的唤起和传参场景再现举个栗子时序图技术方案

  • 场景再现
  • 举个栗子
  • 时序图
  • 技术方案
    • URL Scheme
      • URL Scheme 协议格式
      • Android 实现过程
        • APP A 发起唤起动作
        • APP B 被唤起

场景再现

在开发过程中,会发现有一些业务是需要通过唤起自家不同产品之间的唤起和一些业务操作。例如,可以在产品A直接打开产品B,并且需要在唤起的时候单点登录到B当中。这样可以减少用户的登录操作,有一个比较好的用户体验。

举个栗子

公司有一个 APP A 需要打开 APP B 的时候,如果用户已经在 A 登录了,那打开 B 的时候也需要是登录状态。

时序图

从需求描述,我们可以通过技术讨论,用以下时序图可以描述。

时序图我们可以很清晰的明白我们在不同的模块中所担任的角色和所应该做的事儿。那之后我们就可以进行一个技术方案选型了。

技术方案

APP B

进行token、userId进行校验这一步骤还算简单。但是问题在于我们的

APP A

唤起

APP B

的过程该如何实现。

URL Scheme

如果考虑不同平台中的一致性的话,该方案是最优解。因为这种方案适用于

android

iOS

web

三种平台。

android中的scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面;通过scheme协议,服务器可以定制化告诉App跳转那个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面等。

URL Scheme 协议格式

scheme 最常见的,也是我们最熟悉的,就是

栗子1

所列的,就是我们平常所说的地址。

栗子3

是属于自定义的scheme协议,一般用于自家产品的场景跳转等等,直接打开是没有效的。

// 栗子1
https://baidu.com/app/download?type=android

// 栗子2
http://localhost:8080/index.html

// 栗子3
alipay://platformtype/pay?key1=value1&key2=value2
           

划重点

  1. scheme 协议:栗子当中的https、http、alipay
  2. host 地址域:baidu.com、localhost、platformtype
  3. port 端口:8080(http 协议默认 80 端口、https 协议默认 443 端口,一般默认端口的时候可以忽略端口号,在地址当中不必体现)
  4. 页面\或者具体地址:/app/download、/index.html、/pay
  5. URL参数:type、key1、key2,对应的值依次为:android、value1、value2

Android 实现过程

APP A 发起唤起动作

这里需要注意的是,如果手机没有安装

APP B

APP A

没有做好判断和异常处理,是会导致

APP A

闪退的!

private void openYDDJ() {
    if (isClientAvailable(mContext, "com.padakill.appA")) {
        Intent intent = new Intent("android.intent.action.VIEW");
        Uri uri = Uri.parse("jumpscheme://com.test.padakill/jumpFrom=APP A&userId=f23dada3eab3daefg&token=fw12ea2754dba");
        intent.setData(uri);
        startActivity(intent);
    } else {
        // TODO 打开下载链接
    }
}

/**
 * 判断是否存在该应用
 *
 * @param context   上下文
 * @param appName   APP B 的包名
 * @return  如果存在该应用,则返回true;否则返回false
 */
private boolean isClientAvailable(Context context, String appName) {
    final PackageManager packageManager = context.getPackageManager();
    List<PackageInfo> pinfo = packageManager.getInstalledPackages();
    if (pinfo != null) {
        for (int i = ; i < pinfo.size(); i++) {
            String pn = pinfo.get(i).packageName;
            if (pn.equalsIgnoreCase(appName)) {
                return true;
            }
        }
    }
    return false;
}
           

APP B 被唤起

  1. AndroidManifest.xml

    中配置接受 schemeURL 协议的 activity
    <activity
        android:name="com.padakill.appB.JumpActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
        <intent-filter>
            <!-- 这里即我们前面要求的 schemeURL 规则 -->
            <data
                android:host="com.test.padakill"
                android:scheme="jumpscheme"/>
    
                <!-- 必须添加的属性 -->
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
               
  2. 在 activity 中获取参数等信息,然后进行token验证等业务操作
public class JumpActivity extends Activity {

    @Override
    private void onCreate(Bundle saveInstance) {
        super.onCreate(saveInstance);
        setContentView(R.layout.jumpActivity);

        Uri data = getIntent().getData();
        String uerId = data.getQueryParameter("userId");
        String token = data.getQueryParameter("token");

        // TODO 拿到参数之后即可进行该操作了
    }
}