让Android自动化辅助APP成为设备所有者(一)

简介: 我们之所以需要将Android自动化测试的辅助APP设置成设备所有者是为了更好的控制系统的一些行为从而让整个测试过程更稳定。

DeviceOwner简介


DeviceOwner 是指在设备上以管理员身份运行的应用程序,该应用程序可以使用 DevicePolicyManager 类中的 API 来控制设备的一些行为,例如:重启设备、设置锁屏方式、设置密码、强制清除密码、设置状态栏、设置系统更新策略等。


Android 提供了三种设备管理方案:DeviceAdmin(设备管理员)、ProfileOwner(配置文件所有者) 和 DeviceOwner(设备所有者),这三种设备管理方案的权限大小分别为:DeviceAdmin < ProfileOwner < DeviceOwner。应用需要最大的授权才能成为DeviceOwner,DeviceOwner具有设备的最高权限。


创建DeviceOwner


基本配置

首先在res/xml目录下新建device_admin.xml文件,如下:

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
    <uses-policies>
        <!-- 设置密码规则 -->
        <limit-password />
        <!-- 监视屏幕解锁尝试次数 -->
        <watch-login />
        <!-- 更改解锁密码 -->
        <reset-password />
        <!-- 锁定屏幕 -->
        <force-lock />
        <!-- 清除数据,恢复出厂模式,在不发出警告的情况下 -->
        <wipe-data />
        <!-- 锁屏密码有效期 -->
        <expire-password />
        <!-- 对存储的应用数据加密 -->
        <encrypted-storage />
        <!-- 禁用锁屏信息 -->
        <disable-keyguard-features/>
     <!-- 禁用摄像头 -->
        <disable-camera />
    </uses-policies>
</device-admin>

注册一个自定义广播接收器继承自DeviceAdminReceiver

代码如下:

package com.android.jarvis.receivers
import android.app.admin.DeviceAdminReceiver
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
/**
 * adb shell dpm set-device-owner com.android.jarvis/.receivers.JarvisAdminReceiver
 */
class JarvisAdminReceiver : DeviceAdminReceiver() {
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onEnabled(context: Context, intent: Intent) {
        Log.d("JarvisAdminReceiver", "onEnabled")
        val devicePolicyManager =
            context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
        //设置应用不可卸载
        devicePolicyManager.setUninstallBlocked(
            getComponentName(context),
            context.packageName,
            true
        )
        super.onEnabled(context, intent)
    }
    /**
     * 获取ComponentName,DevicePolicyManager的大多数方法都会用到
     */
    private fun getComponentName(context: Context): ComponentName {
        return ComponentName(
            context.applicationContext,
            JarvisAdminReceiver::class.java
        )
    }
}

在AndroidManifest.xml中注册广播

代码如下:

  <receiver
            android:name=".receivers.JarvisAdminReceiver"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/device_policies" />
            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
                <action android:name="android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED" />
                <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
            </intent-filter>
        </receiver>

激活DeviceOwner



先安装应用,然后在命令行中执行:

adb shell dpm set-device-owner com.android.jarvis/.receivers.JarvisAdminReceiver

移除DeviceOwner


当一个APP成为DeviceOwner后,这个APP是不能被卸载的,也无法在设置中关闭其权限,要想卸载这个APP就必须移除DeviceOwner权限,首先需要在AndroidManifest.xml文件中的<application/>节点添加android:testOnly="true",然后可以通过如下命令移除:

adb shell dpm remove-active-admin com.android.jarvis/.receivers.JarvisAdminReceiver

但是在有些机型上即使设置了testOnly=true也是无法移除,会报以下错误:

java.lang.SecurityException: Attempt to remove non-test admin ComponentInfo{....AppAdminReceiver} 0

这个时候就需要通过代码的方式来移除了,我们可以新建一个广播接收器:

package com.android.jarvis.receivers
import android.app.admin.DevicePolicyManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
/**
 *adb shell am broadcast -a com.android.jarvis.action.DEVICE_ADMIN_DISABLED
 */
class JarvisDeviceReceiver(
    private val ACTION_DEVICE_ADMIN_DISABLED: String = "com.android.jarvis.action.DEVICE_ADMIN_DISABLED"
) :
    BroadcastReceiver() {
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onReceive(context: Context, intent: Intent) {
        val action = intent.action
        if (action == ACTION_DEVICE_ADMIN_DISABLED) {
            val devicePolicyManager =
                context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
            devicePolicyManager.clearDeviceOwnerApp(context.packageName)
        }
    }
}

然后在AndroidManifest.xml文件中注册:

        <receiver android:name=".receivers.JarvisDeviceReceiver">
            <intent-filter>
                <action android:name="com.android.jarvis.action.DEVICE_ADMIN_DISABLED" />
            </intent-filter>
        </receiver>

最后在命令行中执行:

adb shell am broadcast -a com.android.jarvis.action.DEVICE_ADMIN_DISABLED

这样就可以成功移除DeviceOwner权限了。

相关文章
|
3月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
277 0
安卓项目:app注册/登录界面设计
|
3天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
20天前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
|
4月前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
382 2
|
4月前
|
XML Android开发 数据格式
🌐Android国际化与本地化全攻略!让你的App走遍全球无障碍!🌍
在全球化背景下,实现Android应用的国际化与本地化至关重要。本文以一款旅游指南App为例,详细介绍如何通过资源文件拆分与命名、适配布局与方向、处理日期时间及货币格式、考虑文化习俗等步骤,完成多语言支持和本地化调整。通过邀请用户测试并收集反馈,确保应用能无缝融入不同市场,提升用户体验与满意度。
156 3
|
3月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
488 0
|
4月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
3月前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进
本文探讨了如何通过自动化和智能化手段,提升IT运维效率与质量。首先介绍了自动化在简化操作、减少错误中的作用;然后阐述了智能化技术如AI在预测故障、优化资源中的应用;最后讨论了如何构建一个既自动化又智能的运维体系,以实现高效、稳定和安全的IT环境。
97 4
|
3月前
|
运维 Linux Apache
,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具
【10月更文挑战第7天】随着云计算和容器化技术的发展,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具,通过定义资源状态和关系,确保系统始终处于期望配置状态。本文介绍Puppet的基本概念、安装配置及使用示例,帮助读者快速掌握Puppet,实现高效自动化运维。
81 4
|
2月前
|
机器学习/深度学习 运维 监控
智能化运维:从自动化到AIOps的演进之路####
本文深入探讨了IT运维领域如何由传统手工操作逐步迈向高度自动化,并进一步向智能化运维(AIOps)转型的过程。不同于常规摘要仅概述内容要点,本摘要将直接引入一个核心观点:随着云计算、大数据及人工智能技术的飞速发展,智能化运维已成为提升企业IT系统稳定性与效率的关键驱动力。文章详细阐述了自动化工具的应用现状、面临的挑战以及AIOps如何通过预测性分析和智能决策支持,实现运维工作的质变,引领读者思考未来运维模式的发展趋势。 ####

热门文章

最新文章