Android-换个思路实现H5唤醒App并跳转到指定页面

一、H5如何唤醒App

H5唤醒App有多种方式,但一般前端为了同时兼容Android和iOS会采用URL Scheme的形式,下面就重点介绍这种方式。 一个URL Scheme是由以下部分组成的:

[scheme]://[host]:[port][path]?[参数]

说明以及举例

  • scheme是和前端商量好的,一般可以用公司的英文名称,比如淘宝就是taobao,这里举例定义为abc
  • host是主机,可以写公司域名,可以多级,这里举例定义为abc.com
  • port是端口,随便定义,这里举例定义为8088
  • path是路径,随便定义,这里举例定义为/router
  • 参数是前端带给App的参数,这里举例定义为token=123&data={这是一个json字符串}

那么拼出来的URL Scheme就是:

abc://abc.com:8088/router?token=123&data={这是一个json字符串}

在项目中需要根据以上的协议定义一个可以由外部打开的Activity,在清单文件中注册如下:

<!--H5唤起App的中转页面-->
<activityandroid:name=".activity.H5WakeUpNativeActivity"android:exported="true"android:screenOrientation="portrait"tools:ignore="AppLinkUrlError"><intent-filter><dataandroid:host="abc.com"     //这里的参数和前端定义的保持一致android:path="/router"     //这里的参数和前端定义的保持一致android:port="8088"        //这里的参数和前端定义的保持一致android:scheme="abc" />    //这里的参数和前端定义的保持一致<category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><action android:name="android.intent.action.VIEW" /></intent-filter>
</activity>

有了这个Activity之后就可以考虑后续的操作了。

二、思路

唤醒App可能存在以下几个问题:
1、App可能启动了,也可能没启动,没启动的话需要先启动App,启动App后才能跳转,跳转的数据需要存下来。
2、App如果已经在后台了,需要判断用户是否已经登录,如果跳转的目标页面需要登录,那需要先登录后才能跳转到目标界面,跳转的数据需要存下来。
3、想要跳转的目标Activity很多,那么就需要找到一个统一负责跳转和维护的地方。

如果使用数据透传以及ARouter广播通知continue(postCard)的方式实在太麻烦了,可以试试别的思路。

因为一般情况下MainActivity存在App就在,所以将跳转和维护都放在MainActivity中。

我们开发的App一般区分二种情况,一是进MainActivity之前需要登录,二是进MainActivity之前不需要登录,碰到具体操作的时候才需要登录。

下面分别来看。

三、准备工作

1、项目使用ARouter实现跳转,不然组件化的项目拿不到其他模块的Activity的类和对象。
2、项目有维护全局可调用的ViewModel对象,可以看我之前写的一篇文章《Android如何设计一个全局可调用的ViewModel对象?》 本文采用的是博客中的方式二。 (建议点过去看一下,不然有可能看不懂下面的内容)。
3、和前端约定传过来的JSON数据的格式,以下面解析后的结果为例:

/*** H5唤醒App时带过来的数据* 原始Json数据:{"path":"AC001","data":{"id":13786,"user_id":56129},"code":200,"msg":""}*/
data class H5ParamsBean(val path: String = "", //跳转的路径标识val code: Int = 0,val msg: String = "",var data: DataBean? = null, 
) data class DataBean(var id: Int = 0, var user_id: Int = 0
)

其中path字段跳转到哪里和前端同事商量好,比如:

//从 h5 页面经过路由activity跳转至修改密码界面
const val H5_ROUTER_UPDATE_PASSWORD_ACTIVITY = "AC001"//从 h5 页面经过路由activity跳转至忘记密码界面
const val H5_ROUTER_FORGOT_PASSWORD_ACTIVITY = "AC002"//从 h5 页面经过路由activity跳转至注销账号界面
const val H5_ROUTER_CANCEL_ACCOUNT_ACTIVITY = "AC003"//从 h5 页面经过路由activity跳转至意见反馈界面
const val H5_ROUTER_FEED_BACK_ACTIVITY = "AC004"

上面的数据根据自己的需求改成自己实际需要的。这里列出来是为了方便说明。

下面进入正题。

四、需要登录后才能进入MainActivity的App

先从需要登录后才能进入MainActivity的App说起,再讲不需要登录就能进MainActivity的App。

当拿到前端传递过来的数据后,将数据设置给全局可调用的ViewModel对象EventViewModel中的SharedFlow--->h5WakeUpMutableSharedFlow,然后在MainActivity中订阅这个SharedFlow,记住SharedFlowreplay的值要设置为1,因为App没启动时,是先设置值后订阅的,所以数据重放(replay)要设置为1。

先看看H5唤醒原生Activity的代码:

/*** H5跳转到原生页面* 具体传参如下:* abc://abc.com:8088/router?token="123"&data={这是一个json字符串}*/
class H5WakeUpNativeActivity :BaseActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//唤醒AppwakeUpApp()}private fun wakeUpApp() {//判断MainActivity是否在栈中isMainActivityRunning().also { isRunning ->val paramsBean = getParamsBean()if (isRunning) {   //MainActivity在栈中//eventViewModel就是全局可调用的viewmodel的对象,下同//设置唤醒时携带的值eventViewModel.setH5WakeUpValue(paramsBean)} else {   //MainActivity不在栈中eventViewModel.setH5WakeUpValue(paramsBean)//唤醒AppARouter.getInstance().build(ARouterPath.StartActivity).navigation()}}finish()}//获取H5传递过来的值并解析成Bean类private fun getParamsBean(): H5ParamsBean? {val uri = intent.dataif (isRecognizable(uri)) {uri?.getQueryParameter("data")?.apply {if (isNotEmpty()) {try {return GsonUtils.fromJson(this, H5ParamsBean::class.java)} catch (exception: JsonSyntaxException) {LogUtils.d("H5WakeUpNativeActivity JsonSyntaxException")}}}}return null}//是不是需要这个类解析的schemeprivate fun isRecognizable(uri: Uri?): Boolean {return if (uri != null) {val url: String = uri.toString()return url.startsWith("abc://abc.com:8088/router?")} else {false}}/*** 判断MainActivity是否在运行*/private fun isMainActivityRunning(): Boolean {//使用的是AndroidUtilCode库的Api表示感谢ActivityUtils.getActivityList().apply {if (isNotEmpty()) {forEach {if (it::class.java.simpleName == "MainActivity") {return true}}}}return false}
}

这里的逻辑比较简单:
1、拿H5传过来的dataJsonString字符串解析成Bean类。
2、将数据设置给SharedFlow--->h5WakeUpMutableSharedFlow
3、如果MainActivity不在调用栈中,就启动App

上面大部分代码都是解析数据,不管采用什么唤醒方式,基本都是要写的。

下面重点看EventViewModel的代码:

class EventViewModel : ViewModel() {//与viewModel生命周期关联的协程private val coroutineScope: CoroutineScopeget() = viewModelScope/*** H5唤醒App的跳转的Flow*/private val h5WakeUpMutableSharedFlow: MutableSharedFlow<H5ParamsBean> =MutableSharedFlow(replay = 1)       <--------注意这里/*** 设置H5唤醒携带的值*/fun setH5WakeUpValue(bean: H5ParamsBean?) {bean?.apply {h5WakeUpMutableSharedFlow.tryEmit(bean)}}/*** 开始订阅,获取H5唤醒携带的值*/fun getH5WakeUpValue(method: (bean: H5ParamsBean) -> Unit) {coroutineScope.launch(Dispatchers.IO) {h5WakeUpMutableSharedFlow.collect {method.invoke(it)}}}
}

在MainActivity中订阅

eventViewModel.getH5WakeUpValue {//TODO 跳转到具体Activity的业务代码
}

以上方式的优点在于:
1、简洁,除了解析数据,实际的代码就一点点。
2、让MainActivity订阅解决了是否登录的问题,因为登录才能进入MainActivity。
3、使用SharedFlowreplay=1轻松解决了App启动传值和登录传值的问题。因为设置数据在前,MainActivity订阅在后,进入MainActivity还是能拿到数据。

五、不需要登录就能进入MainActivity的App

不需要登录就能进入MainActivity会稍微麻烦一点,因为需要监听登录的状态,但是在EventViewModel中也能轻松的解决。创建一个StateFlow监听登录的状态,然后让它与我们上面定义的SharedFlow--->h5WakeUpMutableSharedFlow联动,当用户登录成功后将未处理完的跳转继续跳转就好了,代码如下:

class EventViewModel : ViewModel() {private var mH5ParamsBean: H5ParamsBean? = null//与viewModel生命周期关联的协程private val coroutineScope: CoroutineScopeget() = viewModelScope/*** 全局的登录状态*/private val loginMutableStateFlow: MutableStateFlow<LoginState> =MutableStateFlow(LoginState.NOT_LOGGED_IN)    //默认未登录val loginStateFlow: StateFlow<LoginState> = loginMutableStateFlow/*** H5唤醒App的跳转*/private val h5WakeUpMutableSharedFlow: MutableSharedFlow<H5ParamsBean> =MutableSharedFlow(replay = 1)/*** 设置登录的状态。登录/退出登录都需要设置。LoginState自定义登录的枚举类。*/fun setLoginState(value: LoginState) {loginMutableStateFlow.value = value}/*** 设置H5唤醒携带的值*/fun setH5WakeUpValue(bean: H5ParamsBean?) {bean?.apply {h5WakeUpMutableSharedFlow.tryEmit(bean)}}/*** 获取H5唤醒携带的值*/fun getH5WakeUpValue(method: (bean: H5ParamsBean) -> Unit) {coroutineScope.apply {launch(Dispatchers.IO) {//H5唤醒原生页面的事件回调h5WakeUpMutableSharedFlow.collect {when (it.path) {"AC006" -> {   //需要登录才能跳转的页面 AC006是举例if (loginStateFlow.value == LoginState.LOGGED_IN) {  //已经登录method.invoke(it)} else {    //未登录//将值存起来mH5ParamsBean = it//跳转到登录页面ARouter.getInstance().build(ARouterPath.LoginActivity).navigation()}}else -> {   //不需要登录就能跳转的页面method.invoke(it)}}}}launch(Dispatchers.IO) {//登录状态的事件回调loginStateFlow.collect { state ->when (state) {LoginState.LOGGED_IN -> {    //用户已登录//用户已登录,继续之前的跳转动作mH5ParamsBean?.apply(method).also {//跳转后参数设置为nullmH5ParamsBean = null}}LoginState.NOT_LOGGED_IN -> {   //用户未登录}}}}}}
}

当用户在登录页面登录成功后,修改登录的StateFlow的状态值,继续完成未完成的跳转事件,这样整个事件就贯穿起来了。也不需要在ARouter拦截器中使用广播那么繁琐了。

扩展
① 如果用户取消了登录,需要清除跳转怎么办?监听登录的StateFlow中增加用户取消登录的状态,适时回调,将数据置为null即可。

② 如果H5需要一次唤醒多个页面跳转,怎么办?那更是Flow的强项了,将数据逐个分发,逐个跳转即可。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/58831.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《低代码指南》——维格云低代码个人设置

目录 1. 简介 1.1 功能简介 1.2 设置内容 1.3 预期效果 2. 详细内容 2.1 基本信息 2.2 账号安全 1. 简介 1.1 功能简介 个人设置是对个人信息的基本设置。管理员及成员可以通过「账户中心 >> 个人设置」修改个人信息。 1.2 设置内容 个人设置里包括基本信息、账…

chatgpt赋能python:Python虚拟环境安装和配置

Python虚拟环境安装和配置 介绍 Python虚拟环境是一种将Python解释器及其相关依赖包隔离开的机制&#xff0c;它使得我们可以在同一计算机上同时安装多个Python版本&#xff0c;并且每个版本可以拥有自己独立的第三方库。 安装 Python自带的venv模块可以用来创建和管理虚拟…

守护进程和后台进程的理解

关于守护进程和后台进程&#xff0c; 一直以为是一个东西。然而并不是。 概念 先看下 chatGPT上对二者的描述&#xff1a; 如何创建守护进程 通常情况下&#xff0c;守护进程的父进程是init进程&#xff08;PID为1&#xff09;。在类Unix系统中&#xff0c;init进程是系统…

chatgpt赋能python:Python拦截手机短信——探索安全应用的新契机

Python拦截手机短信——探索安全应用的新契机 短信成为了我们日常生活中不可或缺的通信手段之一。但是&#xff0c;你是否曾想过&#xff0c;自己的短信是否安全&#xff1f;有没有人会窃取你的短信内容&#xff1f;Python提供了一种新的安全保障方法&#xff0c;就是拦截手机…

php限制访问次数,api接口限流(限制请求次数)

有时候我们需要给我们写的接口来定义请求限制次数(限流) 如多长时间之内只能请求多少次。这样可以防止某些恶意用户一直请求我们的接口 给服务器减轻压力。 应用场景&#xff1a;app端 用户收藏文章 取消收藏文章(某些恶意用户一直在app端重复点击收藏或取消收藏 这样对我们的数…

ChatGPT冷观察:没有大模型的土壤,开不出ChatBot的花

文|智能相对论 作者|叶远风 谁在跟风&#xff0c;谁又有真本事能做出中国版的对标产品来&#xff1f; 这恐怕是ChatGPT这股热潮以来&#xff0c;关心中国AI发展的业界人士最想问的问题。 或者说&#xff0c;在中国人工智能不落后于全世界的当下&#xff0c;业界也在普遍渴望一个…

钉钉PC端聊天中分享的网址生成卡片

前言 卡片化可以方便用户更加简单直接的获取到你网页当中的内容&#xff0c;吸引用户点击进去查看更详细的信息 实现 方式一&#xff1a; 通过设置页面的<meta>标签去获取&#xff1a; <head><meta charset"UTF-8"><meta name"viewpo…

钉钉创建群机器人

1、在对应群&#xff0c;点击右上角设置按钮&#xff1a; 2、点击群智能助手&#xff1a; 3、点击 添加机器人&#xff1a; 4、选择添加 自定义机器人&#xff1a; 5、点击 添加&#xff1a; 6、根据实际情况 选择设置类型&#xff1a; 7、复制得到对应的token值&a…

钉钉群机器人接入

内容摘要 1.简单接入群机器人&#xff0c;主要用于在群里发送通知信息 2.官方API文档&#xff1a;什么是机器人 - 钉钉开放平台 1.创建一个钉钉群&#xff0c;按照下面步骤添加自定义机器人&#xff0c;设置时选择“加签”&#xff0c;创建好之后会得到机器人的webhook 2.机…

钉钉机器人发送卡片消息

1.打开钉钉开放平台&#xff1a;https://open.dingtalk.com/ 2.登陆&#xff08;需要管理员身份&#xff09; 3.开发者后台——创建应用内机器人 4.获得AppKey和AppSecret&#xff0c;用于获取access_token 具体操作官方文档&#xff1a;https://open.dingtalk.com/document/o…

钉钉小程序生态5—钉钉群机器人消息通知和钉钉工作通知

文章导航 钉钉小程序生态1—区分企业内部应用、第三方企业应用、第三方个人应用 钉钉小程序生态2—区分小程序和H5微应用 钉钉小程序生态3—钉钉扫码登录PC端网站 钉钉小程序生态4—钉钉小程序三方企业应用事件与回调 钉钉小程序生态5—钉钉群机器人消息通知和钉钉工作通知 前…

工具使用之——钉钉添加自定义机器人

一 概述 钉钉有自定义机器人功能&#xff0c;开发者可以选择机器人类型(心知天气、代码托管平台&#xff0c;JIRA等)&#xff0c;也可以自定义通过Webhook接入自定义服务的机器人&#xff0c;本篇文章介绍的就是通过Webhook发送通知的机器人 二 添加机器人 点击左侧上方的用户…

利用钉钉接口往钉钉群推送信息

利用钉钉接口往钉钉群推送信息 如下图所示,往钉钉群推送关键信息 创建钉钉群 在群设置中选择智能群助手 选择添加机器人 选择自定义,通过Webhook接入自定义服务

钉钉里的钉一下怎么用 怎么使用钉钉里的钉一下

钉钉是很多公司比较依赖的办公工具&#xff0c;每天上班都要先打开钉钉。我们和同事交流工作内容的时候&#xff0c;主要也是通过钉钉。如果同事消息太多&#xff0c;或者有其他事情耽误了&#xff0c;就可能没有及时查看我们的消息。看着我们发送的消息久久都是“未读”状态&a…

钉钉群机器人消息通知

最近项目需要授权&#xff0c;需要及时通知授权失败的工单&#xff0c;所以就用到了钉钉机器人在群里实时通知&#xff0c;然后就写下了这篇文章。如果放到服务器出现域名错误修改hosts文件,在服务器执行vi /etc/hosts可直接修改&#xff0c;在文件中添加106.11.35.100 oapi.di…

自定义钉钉群机器人

文章目录 一.需求说明二.使用步骤1.打开钉钉&#xff0c;进入一个需要创建机器人的群。并点击群设置2.点击只能群助手&#xff0c;添加机器人3.输入自定义机器人相关信息4.点击确定&#xff0c;保存好webhook5.发送测试 三.官方相关文档 一.需求说明 在做项目的过程中&#xf…

文心源远流长久,百度千帆造万千

摘要 本文介绍了百度文心大模型作为产业级知识增强大模型的特点和应用。文心大模型是百度公司推出的一种技术领先的大型人工智能模型&#xff0c;旨在为千行百业的AI开发提供强大的基座。该模型具有全场景覆盖、技术领先、零门槛使用以及真实可落地的特点。它包括通用的基础大模…

mysql学习之数据系统概述

☀️马上要成为打工人&#xff0c;这几天把前面的知识都捡了捡&#xff0c;发现自己对关系数据库这块的学习还有所缺失&#xff0c;于是本章开始学习mysql 这里写目录标题 1. 数据库系统的发展1.1 人工管理阶段1.2 文件系统阶段1.3 数据库阶段1.4 大数据阶段 2 数据库系统的组…

GPT提示词系统学习-第三课-规范化提示让样本走在提示词前

开篇 本教程将为您提供有关不同类型提示的术语及如何描述它们。尽管提示工程中已经有一些方法来形式化术语,但这个领域仍在不断发展,我们在这篇教程中将给到大家展示一种基于QA形式的通用的、标准的提示语写法。 提示的组成部分 以下是在一个提示中经常会出现的一些组成部…

2023最新软件测试八股文,能不能拿心仪Offer就看你背得怎样了

前言 鉴于目前测试就业越来越严峻&#xff0c;内卷也成了测试领域的代名词了。 所以现在还想从事软件测试行业的小伙伴们&#xff0c;想要心仪的工作&#xff0c;要多努力学习哟。小编给大家整理了2023最新软件测试八股文&#xff0c;大家刷起来哟 1.软件测试基础题&#xff…