前言 有时我们在项目中会不可避免的写一些测试代码(如环境切换,测试页面等等),这些代码可能会存在不同的地方,不方便管理和修改,上线时又不需要把这些代码打进生产包。那么我们能不能以一种非侵入的方式来写这些测试代码呢?组件化开发,我们可以新建一个单独的module,单独用于存放这些测试代码。app模块依赖test module时采用以下方式 debugImplementation project(':module_test') 。 其中,test module 依赖base,base 中有管理activity的工具类。 问题来了,这个test module,如何监听app 的启动并进行一些初始化呢? 方法一 首先肯定是可以使用EventBus或者广播的。我们可以在app启动时发一个通知。 方法二 我们亦可以让test module暴露一个接口或者方法,在application 启动时初始化调用这个方法。 方法三 也可以使用Jetpack 的StartUp组件。
App Startup 库提供了一种在应用程序启动时初始化组件的简单、高效的方法。
使用StartUp实践如下: 在test module中新建以下类:
class TestInitializer : Initializer<Unit> {
override fun create(context: Context) {//这里拿到context是Application
ProcessLifecycleOwner.get().lifecycle.addObserver(ApplicationObserver()) //可以结合Lifecycle监听应用生命周期以获取activity信息
}
override fun dependencies(): MutableList<Class<out Initializer<*>>> = mutableListOf()
}
然后test module的清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.cbim.test">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application>
<activity android:name=".TestActivity"/>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.cbim.test.TestInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>
可以结合Lifecycle监听应用生命周期以获取栈顶的activity信息,因为在Initializer 的 create()时,activity还没创建添加。这里要使用activity进行权限检查和权限申请。
package com.cbim.test
import android.os.Handler
import android.os.Looper
import android.widget.Toast
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import com.alibaba.android.arouter.launcher.ARouter
import com.cbim.guangxi.building.utils.AppManager
import com.cbim.lib_common.router.RouteConstants
import com.lzf.easyfloat.EasyFloat
import com.lzf.easyfloat.enums.ShowPattern
import com.lzf.easyfloat.interfaces.OnPermissionResult
import com.lzf.easyfloat.permission.PermissionUtils
/**
* @Desc:
* @Author: leiertao
* @Date: 2022/8/26
*/
class ApplicationObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
if (PermissionUtils.checkPermission(AppManager.currentActivity())) {
showFloat()
} else {
Toast.makeText(AppManager.currentActivity(),
"请开启悬浮窗权限,方便测试使用",
Toast.LENGTH_SHORT).show()
Handler(Looper.getMainLooper()).postDelayed({
PermissionUtils.requestPermission(AppManager.currentActivity(),
object : OnPermissionResult {
override fun permissionResult(isOpen: Boolean) {
// if (isOpen) showFloat()
}
})
}, 3000)
}
}
private fun showFloat() {
EasyFloat.with(AppManager.currentActivity())
.setLayout(R.layout.float_layout)
.setShowPattern(ShowPattern.FOREGROUND)
.setDragEnable(true)
.registerCallback {
createResult { _, _, view ->
view?.setOnClickListener {
ARouter.getInstance().build(RouteConstants.TEST_ACTIVITY).navigation()
}
}
}
.show()
}
}
我在ApplicationObserver中,开启了一个悬浮按钮。注意,开启悬浮窗需要 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 最终效果如下所示。
这样我们就可以像使用vconsole那样使用悬浮按钮进行测试相关功能的使用了
|