Android正确使用Scheme协议打开App,兼容浏览器scheme的二次跳转 您所在的位置:网站首页 华为浏览器和百度的区别在哪里 Android正确使用Scheme协议打开App,兼容浏览器scheme的二次跳转

Android正确使用Scheme协议打开App,兼容浏览器scheme的二次跳转

2024-05-28 01:42| 来源: 网络整理| 查看: 265

Android正确使用Scheme协议打开App,兼容浏览器scheme的二次跳转 URL Scheme

URL Scheme是一种页面内跳转协议,通过定义自己的URL Scheme协议,可以实现

从一个APP中打开另外一个APP指定的页面从H5页面中跳转到APP指定的页面(实际上就是从一个浏览器中的一个页面跳转到APP指定页面)。

URL Scheme协议格式: 一个完整的完整的URL Scheme协议格式由scheme、host、port、path和query组成,其结构如下所示:

://:/?

如下就是一个自定义的URL openapp://hhong:80/product?productId=10000007 openapp: 即Scheme 该Scheme协议名称(必填) hhong: 即Host,代表Scheme作用于哪个地址域(必填) 80: 即port,代表端口号 product:即path,代表打开的页面 param: 即query,代表传递的参数

传递参数的方法跟web端一样,通过问号?分隔,参数名和值之间使用等号=连接,多个参数之间使用&拼接。

Scheme使用

既然我们使用scheme来做打开app并跳转的逻辑,那这个scheme应该声明在哪里比较合适呢?如果你的应用在启动页(splash)或者在主界面(main)初始化了一些必要的设置,比如必要的token信息检查交易或者一些其它校验等,没有这些信息会造成崩溃的,这个时候我们就需要在启动页来声明这个scheme了,获取scheme信息保存起来,然后在主界面做处理逻辑,如跳转到其它界面等。当然你也可以声明scheme在其它地方,具体得需要看怎么实现业务比较方便。

scheme跳转 scheme跳转 APP1 APP2启动页保存参数 浏览器 APP2主页 APP2具体页面

如配置SplashActivity完整的打开链接为openapp://hhong:80/product?param=100,需要在AndroidManifest.xml配置(SplashActivity启动模式为默认standard模式)

定义好scheme相关的参数后,现在我们需要用scheme调起目标app,主要有两种方式

APP中打开另一个APP指定的页面 String url = "openapp://hhong:80/product?productId=10000007"; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME); Log.e(TAG, "action是:" + intentUri); startActivity(intent);

这种方式的跳转比较简单,也是最不容易出错的。

浏览器中的一个页面跳转到APP指定页面

这种方式的跳转可能同样的代码会导致不同的结果,因为涉及到浏览器,而不同的手机厂商不能保证所有的浏览器内核是一样的,进而可能对scheme的处理也是不一样。 前提:项目用的框架是蚂蚁的MPASS,这个项目可能和正常工程项目不同,因为框架对项目的启动方式做了封装,有兴趣的同学也可以去看下这个框架。 问题:app未启动时,由微信分享出来的链接然后在华为浏览器打开这个链接跳转到指定app时(非桌面图标启动app),第一次是能正常跳转到指定页面,但是app切到后台时,再在华为浏览器打开链接发现竟然不做跳转了,只是将应用切回前台页面,但在小米手机上同样的操作,好像又是正常的,这个把我们搞得一脸懵逼,我们猜测是否和浏览器内核有关,于是我们在Android 自带WebView做scheme的跳转,发现也是正常的。

还有就是浏览器上的scheme跳转,Android这边怎么处理的呢?scheme启动Activity其实用的就是Intent,细心的你肯定发现了第一种方式:APP中打开另一个APP指定的页面的跳转,log打印了一个intentUri:

String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME); Log.e(TAG, "action是:" + intentUri);

打印的结果:

E/MainActivity: action是:intent://hhong:80/product?productId=10000007#Intent;scheme=openapp;end

如果我们在方式1中把intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)加上,打印的结果:

E/MainActivity: action是:intent://hhong:80/product?productId=10000007#Intent;scheme=openapp;launchFlags=0x10000000;end

相比之下,多了个launchFlags字段值,这个值在二次跳转起着重要作用(SplashActivity启动模默认standard),Android FLAG标识和启动模式关系可以看下这两篇文章Android Intent FLAG详解,包括其他的标记的一些解释、Android之点击Home键后再次打开导致APP重启问题,我们把项目SplashActivity的启动模式改为singleTask就完美的实现了我们的需求,此时mpass工程点击桌面图标并不会重新走开屏页SplashActivity。 其实华为推送通知跳转到指定页面时,在控制台上配置的就是这个intent,有兴趣的同学可以去看下华为推送官方文档,看下他们如何定义intent的,所以对于Android来说上面的href标签也可以写成这样:

这两种方式是一样的效果,但是我们从华为浏览器scheme跳转打开app拦截到的intent是携带了FLAG,intent还有些其它的信息,如页面appfilterctrl、当前由哪个应用跳转的application_id。下面是我用正常工程测试浏览器scheme启动跳转app拦截到的intent(测试机是华为手机,可能不同的手机有不同的效果):

华为浏览器 intent://hhong:80/product?productId=10000007#Intent; scheme=openapp; category=android.intent.category.BROWSABLE; launchFlags=0x17000000; launchHwFlags=0x400; component=com.example.aapp/.SplashActivity;end UC浏览器 intent://hhong:80/product?productId=10000007#Intent; scheme=openapp; launchFlags=0x13000000; launchHwFlags=0x400; component=com.example.aapp/.SplashActivity;end Android 自带的WebView intent://hhong:80/product?productId=10000007#Intent; scheme=openapp; category=android.intent.category.BROWSABLE; launchFlags=0x3000000; launchHwFlags=0x400; component=com.example.aapp/.SplashActivity;end 桌面图标启动 intent:#Intent; action=android.intent.action.MAIN; category=android.intent.category.LAUNCHER; launchFlags=0x10200000; component=com.example.aapp/.SplashActivity;sourceBounds=792%201686%201044%202001;end

SplashActivity的启动模式都是默认的standard,最终发现UC浏览器启动app后能正常跳转到页面,但是我再次从浏览器scheme启动app时,不会再跳转指定页面,这一点和桌面启动效果类似,点击桌面图标启动app后,再次点击只会把app切到前台。从上面可以看出主要的区别在于launchFlags,如果将SplashActivity启动模式改为singleTask、singleTop、singleInstance又会是怎样呢?

结论:测试正常工程发现如果SplashActivity的启动模式为standard,scheme二次能否跳转指定页面(能否重新创建SplashActivity)取决于浏览器内核,因为它所携带的launchFlags是不同的;如果SplashActivity的启动模式为singleTask、singleTop、singleInstance,scheme二次都能跳转指定页面,和浏览器内核(携带的launchFlags)无关,但是每次点击桌面图标时都会重新打开app,这个时候我们需要在启动页SplashActivity添加一段代码:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { // finish(); // return; // } // 避免从桌面启动程序后,会重新实例化入口类的activity if (!this.isTaskRoot()) { Intent intent = getIntent(); if (intent != null) { String action = intent.getAction(); if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) { finish(); return; } } } setContentView(R.layout.activity_splash); }

这样就保证了在正常工程下,兼容各种浏览器scheme的二次跳转能正常跳转到指定页面,并且每次点击桌面图标又不会重新打开app了!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有