Android使用Startup和Lifecycle打造一个单独的测试module【转载】

283 阅读2分钟

前言
有时我们在项目中会不可避免的写一些测试代码(如环境切换,测试页面等等),这些代码可能会存在不同的地方,不方便管理和修改,上线时又不需要把这些代码打进生产包。那么我们能不能以一种非侵入的方式来写这些测试代码呢?组件化开发,我们可以新建一个单独的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那样使用悬浮按钮进行测试相关功能的使用了

本文转自 blog.csdn.net/qq_36162336…,如有侵权,请联系删除。