Ruoyi-Android-App 启动页相关协议解析
简介
RuoYi Android App 移动解决方案,采用kotlin框架,实现了与RuoYi-Go 、RuoYi-Vue、RuoYi-Cloud完美对接的移动解决方案!目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。
-
配套后端代码仓库地址RuoYi-Go 或 RuoYi-Vue 或 RuoYi-Cloud 版本。 -
应用框架基于kotlin,支持Android。
启动页作为 Ruoyi-Android-App 的 “门面”,不仅是用户首次接触应用的视觉入口,更是应用上架各大应用市场的核心功能节点 —— 所有涉及用户隐私、设备权限的初始化操作(如推送、IM、地图、通讯录等),必须在用户明确同意相关协议后才能执行。本文将详细解析如何改造 Ruoyi-Android-App 的启动页,实现协议弹窗确认、权限初始化管控的核心功能,满足应用市场上架规范,同时保障用户隐私合规。
一、核心改造思路
本次改造的核心目标是:将应用首次启动页替换为自定义的 SplashActivity,通过 “协议同意状态判断→弹窗确认→权限 / 功能初始化” 的流程,实现合规化管控。具体逻辑如下:
-
首次启动应用时,优先展示 SplashActivity(配置为应用入口); -
读取本地存储的 “协议同意状态”,未同意则弹出协议确认弹窗; -
用户同意协议:记录状态,初始化推送、IM 等功能,跳转登录页; -
用户不同意协议:直接退出应用; -
非首次启动且已同意协议:跳过弹窗,直接初始化功能并跳转登录页。

二、具体实现步骤
1. 配置 SplashActivity 为应用入口
首先创建自定义的 SplashActivity,并在 AndroidManifest.xml 中配置其为应用的启动页,替换原有入口。
(1)创建 SplashActivity 基础类
import android.animation.ValueAnimatorimport android.view.animation.LinearInterpolatorimport com.ruoyi.app.Appimport com.ruoyi.app.databinding.ActivitySplashBindingimport com.ruoyi.app.widget.SplashDialogimport com.ruoyi.app.widget.SplashDialog.SplashDialogClickListenerimport com.ruoyi.code.base.BaseBindingActivityimport com.ruoyi.code.utils.SpUtilsimport java.util.Timerimport java.util.TimerTaskclass SplashActivity : BaseBindingActivity<ActivitySplashBinding>() {private var isAgreement by SpUtils("isAgreement", false)private var timer: Timer? = nulloverride funinitView() {if (!isAgreement) {val splashDialog = SplashDialog(this, object :SplashDialogClickListener{override funonClick(type: Int) {if (type == 1) {isAgreement = truestartActivity()}if (type == 2) {finish()}}} )if (!splashDialog.isShowing) {splashDialog.show()}} else {startActivity()}}override funinitData() {val animator = ValueAnimator.ofFloat(0f, 1f)animator.duration = 1500animator.interpolator = LinearInterpolator()animator.repeatCount = ValueAnimator.INFINITEanimator.addUpdateListener { animation: ValueAnimator ->val value = animation.animatedValue as Float// 计算缩放比例,模拟波浪起伏val scale =(1 + 0.1 * Math.sin(value * 2 * Math.PI)).toFloat()binding.tvWelecome.setScaleX(scale)binding.tvWelecome.setScaleY(scale)}animator.start()}private funstartActivity() {val delayTask = object : TimerTask() {override funrun() {App.init()LoginActivity.startActivity(this@SplashActivity)this@SplashActivity.finish()}}timer = Timer()timer?.schedule(delayTask, 2000)}override funonDestroy() {super.onDestroy()timer?.cancel()timer = null}}
(2)配置 AndroidManifest.xml
将 SplashActivity 配置为应用的主入口,添加 <intent-filter> 标签:
<activityandroid:name=".activity.SplashActivity"android:exported="true" ><intent-filter><actionandroid:name="android.intent.action.MAIN" /><categoryandroid:name="android.intent.category.LAUNCHER" /></intent-filter><!-- 声明支持的语言 --><meta-dataandroid:name="android.content.pm.ActivityInfo.META_DATA_SUPPORTED_LOCALES"android:value="zh,en" /></activity><activityandroid:name=".activity.LoginActivity"android:exported="false"android:launchMode="singleTop" />
2. 封装初始化管理类(InitManager)
将推送、IM、地图、通讯录等功能的初始化逻辑封装到统一的管理类,便于维护:
package com.ruoyi.android.utils;import android.content.Context;import android.Manifest;import android.content.pm.PackageManager;import androidx.core.app.ActivityCompat;/*** 功能初始化管理类:统一处理协议同意后的初始化逻辑*/public class InitManager {/*** 初始化所有核心功能* @param context 上下文*/public static void initAll(Context context) {// 1. 初始化推送功能(如JPush、小米推送等)initPush(context);// 2. 初始化IM功能(如融云、环信等)initIM(context);// 3. 初始化地图功能(如高德、百度地图)initMap(context);// 4. 初始化通讯录权限(需动态申请)initContact(context);}private static void initPush(Context context) {// 推送SDK初始化代码示例// JPushInterface.init(context);// JPushInterface.setDebugMode(true);}private static void initIM(Context context) {// IM SDK初始化代码示例// RongIMClient.init(context, "你的IM AppKey");}private static void initMap(Context context) {// 地图SDK初始化代码示例// AMapLocationClient.updatePrivacyShow(context, true, true);// AMapLocationClient.updatePrivacyAgree(context, true);}private static void initContact(Context context) {// 动态申请通讯录权限(协议同意后才可申请)if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions((android.app.Activity) context,new String[]{Manifest.permission.READ_CONTACTS}, 1001);}}}
companion object {lateinit var application: Applicationfuninit() {ToastUtils.init(application)MMKV.initialize(application)OKHttpUtils.initialize(application)}}
val splashDialog = SplashDialog(this, object :SplashDialogClickListener{override funonClick(type: Int) {if (type == 1) {isAgreement = truestartActivity()}if (type == 2) {finish()}}} )if (!splashDialog.isShowing) {splashDialog.show()}
三、关键逻辑说明
- 1、协议状态持久化 :使用
SharedPreferences存储协议同意状态,即使应用重启,已同意的状态也不会丢失,避免重复弹窗; - 2、弹窗不可取消 :设置
setCancelable(false),确保用户必须选择 “同意” 或 “不同意”,符合应用市场合规要求; - 3、功能初始化时机 :所有涉及设备权限、第三方 SDK 的初始化操作,均放在 “用户同意协议后” 执行,避免未授权情况下获取用户信息;
- 4、退出逻辑:用户不同意协议时,调用
finish()+System.exit(0)彻底退出应用,符合合规要求。
四、上架适配注意事项
-
1、协议内容需完整:弹窗中需明确展示《用户协议》和《隐私政策》的完整内容(可通过跳转网页 / 内置文本实现),仅 “同意 / 不同意” 按钮无法通过应用市场审核; -
2、权限申请合规:通讯录、定位等敏感权限,需在用户同意协议后再动态申请,且需说明权限使用场景; -
3、状态回显:若用户后续在设置中取消协议同意,需重新触发弹窗逻辑(可在应用启动时再次检查状态)。
总结
本次 Ruoyi-Android-App 启动页改造的核心要点:
-
1、通过配置 <intent-filter>将 SplashActivity 设为应用入口,掌控首次启动流程; -
2、基于 SharedPreferences实现协议同意状态的持久化判断,未同意则弹窗、同意则直接初始化; -
3、所有权限 / 第三方 SDK 初始化操作需在用户同意协议后执行,满足应用市场上架合规要求; -
4、封装 InitManager 统一管理初始化逻辑,提升代码可维护性。
夜雨聆风
