外部唤起App跳转到指定页面(区分返回原页面)

需求背景

产品经理要求从系统日历点击商品链接跳转浏览器, 再由浏览器跳转到APP指定的商品详情页面, 点击导航栏返回按钮或者物理回退键返回原页面,若APP未启动, 则返回首页。

1.在目标Activity清单文件中添加
          
                
                
                
                
            
2.目标Activity的onCreate方法匹配H5规则, 获取业务数据
        Intent intent = getIntent();
        Uri uri = null;
        if(intent != null) {
            uri = intent.getData();  获取H5规则, 可携带数据
            String scheme = getIntent().getScheme();
            KLog.i("scheme" + scheme);
        }

        if (uri != null) {
            isFromBrowser = true; //区分是否从浏览器唤起的标记,自行定义成员变量
            String praseItemId = uri.getQueryParameter("itemId");
            String praseActivityId = uri.getQueryParameter("limitActivityId");
            try {
                itemId = Integer.valueOf(praseItemId);
                limitActivityId = Integer.valueOf(praseActivityId);
            }catch (Exception e) {
                KLog.e(TAG, "handleBrowserEvoke() : " + e.getMessage());
            }
            url = addShopId(URIConstants.getItemDetailUrl() + "itemId=" + itemId); //拼装webview加载url
        }
3.根据app唤起之前的状态区分三种情况处理

首先确认你的应用是否有一个必须打开的activity, 我的应用是首页ACT_main
思路: 判断首页是否在栈内, 若在栈内, 说明你的应用已经启动, 直接关闭目标activity即可, 如果不在栈内, 说明你的APP还未启动过, 结合步骤2加的 isFromBrowser标记来区分处理.

 /**
     * 检查目标activity是否启动
     * @param context
     * @param clazz 传入ACT_main
     * @return
     */
    public boolean isLaunchedActivity(@NonNull Context context, Class clazz) {
        Intent intent = new Intent(context, clazz);
        ComponentName cmpName = intent.resolveActivity(context.getPackageManager());
        boolean flag = false;
        if (cmpName != null) {
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            List taskInfoList = am.getRunningTasks(10);
            for (ActivityManager.RunningTaskInfo taskInfo : taskInfoList) {
                if (taskInfo.baseActivity.equals(cmpName)) {
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

然后, 在点击返回监听和物理键返回回调中做以下处理
(1) APP未启动
判断isFromBrowser == true, isLaunchedActivity返回false, 可以直接启动首页

    Intent intent = new Intent(activity, ACT_Main.class);
    intent.putExtra("currentIndex", index);
    activity.startActivity(intent);

(2) APP已打开, 并且A页面就是链接跳转的商品详情
判断isFromBrowser == true, isLaunchedActivity返回true, 在目标Activity清单文件中设置对应的启动模式, 防止重复打开两个目标页面

    android:launchMode="singleTop"  如果多个页面复用一个webview, 此方式不适用

(3) APP已打开,进入的是其他页面(非A页面)
判断isFromBrowser == true, isLaunchedActivity返回true, 关闭目标Activity

    目标Activity.finish(); 目前仅oppo手机使用, 其他手机请关注下面兼容问题的解决方法
4.兼容问题

1.oppo手机从浏览器唤起,不会走onCreate方法,导致不会重新加载webview。(华为,小米无此问题)
解决方法:在页面onNewIntent方法中,重新请求H5规则,然后重新打开一次

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //oppo手机从浏览器唤起, 如果WebView已打开, 不会走onCreate方法, 导致无法打开指定商详
        //这里重新获取H5规则和参数, 然后重新开启一次activity
        if(RomUitls.isOppo()) {  //判断是否为oppo手机, 请自行百度
            handleBrowserEvoke(intent); //再次重复步骤1
            if(isFromBrowser) {
                ACT_ItemDetail.launch(this, mItemId, 0, limitActivityId, false);
            }
        }
    }

2.从浏览器唤起指定商详,点击app商详上的返回按钮上,再从后台切回到浏览器,这时候浏览器展示的还是栈内的商详页
解决方法:判断如果是浏览器唤起,并且在app商详点击了返回,onResume方法中finish。

@Override
    protected void onResume() {
        super.onResume();
        if(isReturnBrowser) {   //判断如果是浏览器唤起,并且在app商详点击了返回标记
            finish();
        }
    }

3.华为和小米手机从浏览器唤起,指定商详页加入了浏览器的栈内,这时候你点击app商详返回按钮, 只是finish掉了浏览器的栈内的商详页, app本身还在后台运行,要求是点击返回后app要到前台,目前发现oppo手机可以,可能是厂家定制系统做了相关处理。
解决方法:当关闭浏览器的栈内的商详,将app切换到前台运行, 确保回到用户操作的原页面。

    /**
     * 处理浏览器唤起app跳转商详,点击返回按钮或物理回退键的逻辑
     */
    private void fromBrowserRetrurnType() {
        //如果从浏览器跳转过来, 并且主页从未打开, 返回需要进入首页
        if(isFromBrowser) {
            if(!isLaunchedActivity(ACT_ItemDetail.this, ACT_Main.class)) {
                ACT_Main.launch(this, ACT_Main.Type_select);
            } else {
                isReturnBrowser = true; //判断如果是浏览器唤起,并且在app商详点击了返回标记
                //获取ActivityManager
                ActivityManager mAm = (ActivityManager) this.getSystemService(Activity.ACTIVITY_SERVICE);
                //获得当前运行的task
                List taskList = mAm.getRunningTasks(100);
                for (ActivityManager.RunningTaskInfo rti : taskList) {
                    //找到当前应用的task,并启动task的栈顶activity,达到程序切换到前台
                    if(rti.topActivity.getPackageName().equals(this.getPackageName())) {
                        mAm.moveTaskToFront(rti.id,0);
                    }
                }
            }
        }
    }

至此, 这个需求基本做完了, 但不是很完美, 还请大神多多赐教.
另外贡献一个好博客: http://www.jianshu.com/p/1439c8bbc34b

你可能感兴趣的:(外部唤起App跳转到指定页面(区分返回原页面))