如何編寫基於Android的AccessibilityService的釘釘自動打卡


第一節 緣由與准備 

最近有時間空閑,閑來無事,想到使用釘釘打卡有時會遲到,所以周末的時候去看了相關網上資料,做了個demo。

材料:定時器,AccessibilityService

加工方案:使用定時器在簽到簽退期間內自啟,通過AccessibilityService模擬點擊:分為簽到與簽退兩種情況。

簽到正常流程:工作-》考勤打卡-》(判斷是否彈出窗口-是:我知道了否跳過)-》簽到。

簽到遲到流程:工作-》考勤打卡-》遲到打卡。

簽退正常流程:工作-》考勤打卡-》簽退。

工藝難點:簽到頁中嵌套的是基於WebView的頁面,一開始以為無法獲取節點,想到通過屏幕中的位置去點擊那塊區域,查看官方文檔發現有個方法getAccessibilityNodeProvider(),得到虛擬節點進行模擬點擊。

第二節:熱火朝天

技能點:判斷應用狀態,啟動指定應用,自定義AccessibilityService控制模擬點擊流程

判斷應用狀態:

 

 public static boolean isBackground(Context context) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(context.getPackageName())) {
                if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    Log.i("后台", appProcess.processName);
                    return true;
                }else{
                    Log.i("前台", appProcess.processName);
                    return false;
                }
            }
        }
        return false;
    }

 

  

 

啟動指定應用:

 

 public static void doStartApplicationWithPackageName(Context context, String packagename) {

        // 通過包名獲取此APP詳細信息,包括Activities、services、versioncode、name等等
        PackageInfo packageinfo = null;
        try {
            packageinfo = context.getPackageManager().getPackageInfo(packagename, 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        if (packageinfo == null) {
            return;
        }

        // 創建一個類別為CATEGORY_LAUNCHER的該包名的Intent
        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        resolveIntent.setPackage(packageinfo.packageName);

        // 通過getPackageManager()的queryIntentActivities方法遍歷
        List<ResolveInfo> resolveinfoList = context.getPackageManager()
                .queryIntentActivities(resolveIntent, 0);

        ResolveInfo resolveinfo = resolveinfoList.iterator().next();
        if (resolveinfo != null) {
            // packagename = 參數packname
            String packageName = resolveinfo.activityInfo.packageName;
            // 這個就是我們要找的該APP的LAUNCHER的Activity[組織形式:packagename.mainActivityname]
            String className = resolveinfo.activityInfo.name;
            // LAUNCHER Intent
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);

            // 設置ComponentName參數1:packagename參數2:MainActivity路徑
            ComponentName cn = new ComponentName(packageName, className);

            intent.setComponent(cn);
            context.startActivity(intent);
        }
    }

 

自定義AccessibilityService控制模擬點擊流程:

1.獲取點擊控件對象(可以通過文本不推薦通過資源id方式點擊)

工作布局的資源ID:

 

考勤打卡布局的資源ID(這個id是動態生成的8個都是):

考勤打卡布局的資源ID:

2窗口發生變化處理:

 @Override
    public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
        if(isFinish){
            return;
        }
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if(nodeInfo == null) {
            Log.d(TAG, "rootWindow為空");
            return ;
        }
        switch (accessibilityEvent.getEventType()){
            //當窗口的狀態發生改變時
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
               if (index==1) {
                    //主頁點擊工作
                   clickHome(nodeInfo,accessibilityEvent);
                   Log.d(TAG,"工作");
                } else  if (index==2) {
                    //工作tab點擊考勤打卡
                   clickKaoQing(nodeInfo,accessibilityEvent);
                   Log.d(TAG,"點擊考勤打卡");
                } else  if (index==3) {
                    //開始打卡
                   clickKaoQingBtn(nodeInfo,accessibilityEvent);
                   Log.d(TAG,"打卡");
                }
                break;
        }

    }

 

3后續處理:

發現考勤打卡頁面是基於webview的h5頁面,因此暫時沒有好的方法,獲取webview對象,以及獲取虛擬節點。

不過如果可以獲取到窗口下的webview對象,那么是可以獲取頁面的虛擬節點,進行模擬點擊。打卡是沒問題的,由於現在極速打卡的功能,打開應用自動簽到。

參考:

>Android WebView官方文檔

>Android AccessibilityNodeProvider官方文檔

>基於AccessibilityService制作的釘釘自動簽到程序


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM