android 免root智能辅助无障碍完成自动更新软件流程

原理:在app添加一个智能辅助服务然后在设置界面打开智能辅助即可在服务中监听屏幕各种状态,我们可以监听安装的install包然后监听安装弹框的“安装”点击按钮,监听到直接进入安装流程就可以了

如果需要自动开启辅助功能可以参考:Android 应用自动开启辅助(无障碍)功能并使用辅助(无障碍)功能_android 自动开启无障碍服务_龚礼鹏的博客-CSDN博客

可能上面说的比较绕,下面直接来流程:

1.manifes中的配置如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.midea.cabinet">

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/><!-- 8.0系统安装apk权限 -->

        <!-- 下载后安装apk。注:7.0及以上系统禁止直接访问storage私有文件,需通过FileProvider生成content://URI去授予临时访问的权限,实现应用间数据共享 -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

        <!--
    android:label(可选) 在辅助功能(无障碍)的系统设置会使用该名称,若不设置,则会使用<application android:label
    android:process(可选) 把该服务设在单独进程中,进程名以[冒号:]开头,是本应用的私有进程,其它应用无法访问
    android:permission(必需) 添加权限以确保只有系统可以绑定到该服务
    -->
        <service
            android:name=".updateApk.AutoInstallService"
            android:label="自动安装"
            android:process=":install"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>

            <!--在xml文件配置辅助功能,也可在onServiceConnected()中使用setServiceInfo()动态配置-->
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_config" />
        </service>
    </application>

</manifest>

2.res中新建xml文件夹然后添加两个文件分别是accessibility_config.xml和file_paths.xml,内容如下所示:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/install_smart"
    android:packageNames="com.android.packageinstaller"
    android:notificationTimeout="100"/>
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- apk存放路径:getExternalCacheDir()/apk/xiaomaigui.apk -->
    <external-cache-path name="externalcache" path="apk" />
    <cache-path name="cache" path="apk"/>
    <!--Environment.getExternalStorageDirectory()/xiaomaigui/-->
    <external-path
        name="externalpath"
        path="midea/ApkUpgrade"/>
    <root-path name="root" path="system"/>
</paths>

3.添加辅助服务AutoInstallService:

package com.midea.cabinet.updateApk;

import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import com.blankj.utilcode.util.LogUtils;

import java.util.HashMap;
import java.util.Map;

public class AutoInstallService extends AccessibilityService {
    private Map<Integer, Boolean> handleMap = new HashMap<>();

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        AccessibilityNodeInfo nodeInfo = event.getSource();
        if (nodeInfo != null) {
            int eventType = event.getEventType();
            if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                if (handleMap.get(event.getWindowId()) == null) {
                    boolean handled = iterateNodesAndHandle(nodeInfo);
                    if (handled) {
                        handleMap.put(event.getWindowId(), true);
                    }
                }
            }
        }
    }

    @Override
    public void onInterrupt() {
    }
    // 遍历节点,模拟点击安装按钮
    private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo != null) {
            int childCount = nodeInfo.getChildCount();

            if ("android.widget.Button".equals(nodeInfo.getClassName())) {
                String nodeCotent = nodeInfo.getText().toString();
                LogUtils.d("content is: " + nodeCotent);
                LogUtils.e("nodeInfo"+nodeInfo.getClassName());
                if ("安装".equals(nodeCotent) || "打开".equals(nodeCotent)) {
                    nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    return true;
                }
            }
            // 遇到 ScrollView 的时候模拟滑动一下
            else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {
                nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            }
            for (int i = 0; i < childCount; i++) {
                AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
                if (iterateNodesAndHandle(childNodeInfo)) {
                    return true;
                }
            }
        }
        return false;
    }
}

4.编写安装代码:

/**
     * apk安装
     */
    private fun installApp(apkPath: String) {
        val file = File(apkPath)
        val intent = Intent()
        intent.action = Intent.ACTION_VIEW
        val data = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
            FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", file)
        } else {
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            Uri.fromFile(file)
        }
        intent.setDataAndType(data, "application/vnd.android.package-archive")
        startActivity(intent)
    }

以上 即可完成辅助功能免root安装 需要用户在设置界面的无障碍辅助中打开自己的服务,我上面写的就是需要打开自动安装。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚礼鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值