需求背景
产品经理要求从系统日历点击商品链接跳转浏览器, 再由浏览器跳转到APP指定的商品详情页面, 点击导航栏返回按钮或者物理回退键返回原页面,若APP未启动, 则返回首页。
1.在目标Activity清单文件中添加
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
//app唯一标记
android:scheme="xxxvip"/>
</intent-filter>
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<ActivityManager.RunningTaskInfo> 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<ActivityManager.RunningTaskInfo> 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
网友评论