com.ucmap.dingdinghelper.services.DingDingHelperAccessibilityService.java Source code

Java tutorial

Introduction

Here is the source code for com.ucmap.dingdinghelper.services.DingDingHelperAccessibilityService.java

Source

/*
 * Copyright (C)  Justson(https://github.com/Justson/DingDingHelper)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ucmap.dingdinghelper.services;

import android.accessibilityservice.AccessibilityService;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import com.ucmap.dingdinghelper.R;
import com.ucmap.dingdinghelper.app.App;
import com.ucmap.dingdinghelper.common.OrderThread;
import com.ucmap.dingdinghelper.entity.AccountEntity;
import com.ucmap.dingdinghelper.entity.MessageEvent;
import com.ucmap.dingdinghelper.sphelper.SPUtils;
import com.ucmap.dingdinghelper.ui.MainActivity;
import com.ucmap.dingdinghelper.utils.Constants;
import com.ucmap.dingdinghelper.utils.DateUtils;
import com.ucmap.dingdinghelper.utils.DingHelperUtils;
import com.ucmap.dingdinghelper.utils.JsonUtils;
import com.ucmap.dingdinghelper.utils.ShellUtils;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;

import static com.ucmap.dingdinghelper.utils.DateUtils.getHourAndMin;

/**
 * author Just  
 * <p>
 * 1.AccessibilityService oom_adj 1s1   ??adj0 
 * ?? ? ???service
 * <p>
 * 2.?root?root ??
 * <p>
 * 3.??  ?10s
 * ??? ????????(ID???)
 * 4.AlarmManager ? ?1s  6AlarmManager ???note8?
 * ? AlarmManager Android5.0TimgService  TimingService?
 * ??.
 */
public class DingDingHelperAccessibilityService extends AccessibilityService {

    /**/
    private static final String SURE_EXCEPTION_ID = "android:id/button1";
    /*ID*/
    private static final String CONFIRM_QUIT_ID = "android:id/button1";
    /*???*/
    private static final String PHONE_ID = "com.alibaba.android.rimet:id/et_phone_input";
    /*?*/
    private static final String PASSWORD_ID = "com.alibaba.android.rimet:id/et_pwd_login";
    /**/
    private static final String BUTTON_ID = "com.alibaba.android.rimet:id/btn_next";
    /*Bottom ?*/
    private static final String HOME_BOTTOM_ID = "com.alibaba.android.rimet:id/bottom_tab";
    /*?*/
    private static final String HOME_BOTTOM_WORK_ID = "com.alibaba.android.rimet:id/home_bottom_tab_button_work";
    /*??*/
    private static final String TAB_COMPANY_INDEX_ID = "com.alibaba.android.rimet:id/menu_current_company";
    /*?RecyclerView id*/
    private static final String RECYCLERVIEW_WORK_ID = "com.alibaba.android.rimet:id/oa_fragment_gridview";
    /*webView*/
    private static final String CHECK_IN_PAGER_TAGET = "com.alibaba.lightapp.runtime.activity.CommonWebViewActivity";
    /*?*/
    private static final String SETTINGWINDOW = "com.alibaba.android.user.settings.activity.NewSettingActivity";
    /**/
    private volatile boolean runing_monitor = true;
    /*?*/
    public static final String LOGINWINDOW = "com.alibaba.android.user.login.SignUpWithPwdActivity";
    /*?*/
    private static final String HOMEWINDOW = "com.alibaba.android.rimet.biz.home.activity.HomeActivity";
    /*??*/
    private static String CURRENT_WINDOW = "";
    /*???*/
    private static boolean isCheckIn = false;
    /**/
    //    private MonitorThread mMonitorThread;
    /**/
    private static int STATE = 0;
    /*?????*/
    private static final int STATE_CHECKED_IN = 1;
    /*????*/
    private static final int STATE_UNCHECKED_IN = 0;
    /*????  ?*/
    private static final int STATE_RELEASE = -1;
    /**
     * ID
     */
    private static final int NOTIFICATION_ID = 0x000088;
    /*??*/
    private static final String DING_DING_PAGKET_NAME = "com.alibaba.android.rimet";

    private static final String WEBVIEW_PARENT = "com.alibaba.android.rimet:id/common_webview";

    private static final String AFTER_WORK = "??";
    private static final String GO_TO_WORK = "??";

    private static final String ALERT_DIALOG_WINDOW = "android.app.AlertDialog";

    /**
     * ID
     */
    private static final String HOME_MINE_ID = "com.alibaba.android.rimet:id/home_bottom_tab_button_mine";
    /*ID*/
    private static final String MINE_SETTING_ID = "com.alibaba.android.rimet:id/rl_setting";
    /*ID*/
    private static final String SETTING_SIGN_OUT_ID = "com.alibaba.android.rimet:id/setting_sign_out";
    /*?Fragment ?*/
    private static String CURRENT_PAGER = "message";
    private static final String MESSAGE_PAGER = "message";
    private static final String DING_PAGER = "ding";
    private static final String TCN_PAGER = "tcn";
    private static final String CONTACT_PAGER = "contact";
    private static final String MINE_PAGER = "mine";

    private static final String HEADER_MINE_ID = "com.alibaba.android.rimet:id/header_mine";
    private static final String HEADER_CONTACT_ID = "com.alibaba.android.rimet:id/header_contact";
    private static final String HEADER_DING = "com.alibaba.android.rimet:id/header_ding";
    private static final String HEADER_MESSAGE = "com.alibaba.android.rimet:id/header_message";

    /*??*/
    private static final String CHECK_IN_PAGER_BACK = "com.alibaba.android.rimet:id/back_layout";
    /**
     * ???????
     */
    private static final int TIME_LIMIT = 12;
    private List<AccountEntity> mAccountEntities;

    /*service???*/
    public static volatile boolean IS_ENABLE_DINGDINGHELPERACCESSIBILITYSERVICE = false;

    @Override
    public void onCreate() {
        super.onCreate();
        EventBus.getDefault().register(this);
        IS_ENABLE_DINGDINGHELPERACCESSIBILITYSERVICE = true;
    }

    /**
     * TimingBroadcastReceiver ?  ?
     *
     * @param messageEvent
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent messageEvent) {

        if (messageEvent.getFlag_bit() == Constants.RESET_PASSWORD) {
            init();
            return;
        }

        if (messageEvent != null && messageEvent.getFlag_bit() == 1) {
            isChecking = false;
        }
        doCheckIn();
    }

    /**
     * ??
     */
    @Override
    protected void onServiceConnected() {
        Toast.makeText(this.getApplicationContext(), "???", Toast.LENGTH_SHORT).show();
        super.onServiceConnected();
        init();
        increasePriority();
    }

    /*???service */
    private void increasePriority() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            Notification.Builder mBuilder = new Notification.Builder(this);
            mBuilder.setSmallIcon(R.mipmap.ic_launcher);
            startForeground(NOTIFICATION_ID, mBuilder.build());
            InnerService.startInnerService(this);
        } else {
            startForeground(NOTIFICATION_ID, new Notification());
        }
    }

    /**
     * ?
     */
    private int hour = 8;
    private int min = 30;

    /**
     * ??
     */
    private AccountEntity targetCheckInAcount = new AccountEntity();

    /**
     * 
     */
    private int index = 0;

    private void init() {

        String jsonAccountList = (String) SPUtils.getString(Constants.ACCOUNT_LIST, "-1");
        if (TextUtils.isEmpty(jsonAccountList) || "-1".equals(jsonAccountList)) {
            Toast.makeText(App.mContext, "???", Toast.LENGTH_SHORT).show();
            return;
        }
        mAccountEntities = JsonUtils.listJson(jsonAccountList, AccountEntity.class);
        if (mAccountEntities == null || mAccountEntities.isEmpty()) {
            Toast.makeText(App.mContext, "???", Toast.LENGTH_SHORT).show();
            return;
        }
        doScript();
    }

    private void doScript() {
        if (mAccountEntities == null)
            return;
        if (index >= mAccountEntities.size())
            return;
        targetCheckInAcount = mAccountEntities.get(index++);

        STATE = STATE_UNCHECKED_IN;

        String current = getHourAndMin(System.currentTimeMillis());
        int hour = Integer.parseInt(current.split(":")[0]);
        String time = "";
        if (hour < TIME_LIMIT) {
            time = (String) SPUtils.getString(Constants.MORNING_CHECK_IN_TIME, "8:45");
        } else {
            time = (String) SPUtils.getString(Constants.AFTERNOON_CHECK_IN_TIME, "20:45");
        }

        if (time.length() >= 4) {
            String[] hourAndMin = time.split(":");
            this.hour = Integer.parseInt(hourAndMin[0]);
            this.min = Integer.parseInt(hourAndMin[1]);
        }

    }

    private long tag_callback_time = 0;

    /**
     * ???
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        tag_callback_time = System.currentTimeMillis();
        int eventType = event.getEventType();

        Log.i("Info",
                " eventType: " + eventType + "   getEventTime:  " + event.getEventTime() + "     getAction"
                        + event.getAction() + "getContentChangeTypes:" + event.getContentChangeTypes()
                        + " getText :" + event.getText().toString() + "getPackageName :" + event.getPackageName()
                        + "getRecordCount : " + event.getRecordCount() + "  getClassName:" + event.getClassName()
                        + "  :" + event.getClass() + "   getParcelableData:" + event.getParcelableData());

        switch (eventType) {
        /*??*/
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
            windowContentChanged();
            break;
        //???
        case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
            notificationChanged(event);
            break;
        //Activity???
        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
            windowChanged(event);
            break;
        }
    }

    private void windowChanged(AccessibilityEvent event) {
        String className = event.getClassName() + "";
        /*??*/
        DingDingHelperAccessibilityService.CURRENT_WINDOW = className;
        if (findById(HOME_BOTTOM_WORK_ID) != null) {
            DingDingHelperAccessibilityService.CURRENT_WINDOW = HOMEWINDOW;
        }
        /*???*/
        if (className.equals(LOGINWINDOW) && STATE == STATE_UNCHECKED_IN) {
            toSignIn();
        } else if (HOMEWINDOW.equals(className)) {
            if (STATE == STATE_UNCHECKED_IN)
                performWaitCheckIn();
            else if (STATE == STATE_UNCHECKED_IN)
                switchMine();

        } else if (CHECK_IN_PAGER_TAGET.equals(className)) {
            if (STATE != STATE_CHECKED_IN) {
                openCheckInDialog();
            } else {
                backHomePager();
            }
        } else if (SETTINGWINDOW.equals(className) && STATE != STATE_UNCHECKED_IN) {
            inputClick(SETTING_SIGN_OUT_ID);
        } else if (ALERT_DIALOG_WINDOW.equals(className)) {
            List<AccessibilityNodeInfo> mAccessibilityNodeInfos = new ArrayList<>();
            /*?,?*/
            recurseFindByTextToList("", this.getRootInActiveWindow(), mAccessibilityNodeInfos);
            if (mAccessibilityNodeInfos != null && !mAccessibilityNodeInfos.isEmpty())
                inputClick(SURE_EXCEPTION_ID);
            List<AccessibilityNodeInfo> mNodeQuit = new ArrayList<>();
            recurseFindByTextToList("", this.getRootInActiveWindow(), mNodeQuit);
            if (mNodeQuit != null && !mNodeQuit.isEmpty())
                doQuit();
        }
    }

    private static final String DD_PROGRESS_DIALOG = "com.alibaba.android.dingtalkbase.widgets.dialog.DDProgressDialog";
    private Handler mHandler = new Handler(Looper.getMainLooper());

    /*????,???*/
    private void handleHomeInsensitiveCallback(final long time) {

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {

                if (DingDingHelperAccessibilityService.this == null)
                    return;
                // DingDingHelperAccessibilityService.CURRENT_WINDOW.equals(DingDingHelperAccessibilityService.DD_PROGRESS_DIALOG)
                if (DingDingHelperAccessibilityService.this.tag_callback_time == time
                        || DingDingHelperAccessibilityService.CURRENT_WINDOW
                                .equals(DingDingHelperAccessibilityService.CHECK_IN_PAGER_TAGET))
                    ShellUtils.execCmd("input swipe 300 800 300 500", true);
            }
        }, 2000);

    }

    private void notificationChanged(AccessibilityEvent event) {
        try {

            List<CharSequence> mCharSequences = event.getText();
            if (mCharSequences == null || mCharSequences.isEmpty())
                return;
            StringBuffer sb = new StringBuffer();
            for (CharSequence c : mCharSequences) {
                sb.append(c.toString());
            }
            if (!sb.toString().contains("?"))
                return;
            Parcelable mParcelable = event.getParcelableData();
            if (mParcelable != null && mParcelable instanceof Notification) {
                Notification mNotification = (Notification) mParcelable;
                PendingIntent mPendingIntent = mNotification.contentIntent;
                if (mPendingIntent == null)
                    return;
                /**/
                mPendingIntent.send();
            }
        } catch (Exception e) {

        }
    }

    private void windowContentChanged() {
        switch (CURRENT_WINDOW) {

        case HOMEWINDOW:
            setCurrentPagerId();

            /*????*/
            if (STATE == STATE_UNCHECKED_IN) {
                /*???*/
                boolean isCheckInPager = isCheckInPager();
                if (!isCheckInPager) {
                    performWaitCheckIn();
                } else {
                    /*????*/
                    openCheckInPager();
                }
            } else if (STATE == STATE_CHECKED_IN) {//????

                if (MINE_PAGER.equals(CURRENT_PAGER)) {//?????  
                    inputClick(MINE_SETTING_ID);
                } else {
                    /*??*/
                    switchMine();
                }

            }
            break;
        case CHECK_IN_PAGER_TAGET:
            try {
                if (STATE != STATE_CHECKED_IN) {
                    openCheckInDialog();
                } else {
                    finishSignIn();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            break;
        case SETTINGWINDOW:
            //                doQuit();
            break;
        case DingDingHelperAccessibilityService.LOGINWINDOW:
            if (STATE == STATE_UNCHECKED_IN) {
                toSignIn();
            }
            break;

        }
    }

    private void finishSignIn() {
        AccessibilityNodeInfo mAccessibilityNodeInfo = this.getRootInActiveWindow();
        if (mAccessibilityNodeInfo == null) {
            return;
        }
        AccessibilityNodeInfo mNodeInfos = recurseFindByText("?", mAccessibilityNodeInfo);//??? 
        if (mNodeInfos == null) {
            backHomePager();
            handleHomeInsensitiveCallback(tag_callback_time);
            return;
        }
        AccessibilityNodeInfo mInfo = mNodeInfos;
        Rect mRect = new Rect();
        mInfo.getBoundsInScreen(mRect);

        doShellCmdInputTap(mRect.centerX(), mRect.centerY());//adb? ??root

        backHomePager();
    }

    /*DingDingHelperAccessibilityService*/
    private void closeHelperService() {

        List<String> mList = new ArrayList<>();
        mList.add(Constants.POINT_SERVICES_ORDER);
        mList.add(Constants.DISENABLE_SERVICE_PUT);
        //?
        mList.add("am force-stop " + DING_DING_PAGKET_NAME);

        /*????*/
        if (DingHelperUtils.isScreenLight(App.mContext))
            mList.add("input keyevent 26");
        //        ShellUtils.execCmd(mList, true);
        new OrderThread(mList).start();

    }

    /**/
    private void doQuit() {
        AccessibilityNodeInfo mAccessibilityNodeInfo = findById(CONFIRM_QUIT_ID);
        if (mAccessibilityNodeInfo != null && mAccessibilityNodeInfo.isClickable()) {
            STATE = STATE_RELEASE;
            mAccessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            isChecking = false;
            if (mAccountEntities == null)
                return;
            if (index >= mAccountEntities.size()) {
                String[] hm = DateUtils.getHourAndMin(System.currentTimeMillis()).split(":");
                if (Integer.parseInt(hm[0]) > TIME_LIMIT) {
                    index = 0;
                    targetCheckInAcount = mAccountEntities.get(index++);
                }
                closeHelperService();
                return;
            }

            doScript();

            if (STATE == STATE_UNCHECKED_IN) {
                toSignIn();
            }

        }
    }

    /*?ActivityFragment*/
    private void setCurrentPagerId() {

        List<AccessibilityNodeInfo> listMine = null;
        AccessibilityNodeInfo mAccessibilityNodeInfo = getRootInActiveWindow();
        if (mAccessibilityNodeInfo == null)
            return;
        listMine = mAccessibilityNodeInfo.findAccessibilityNodeInfosByViewId(HEADER_MINE_ID);
        if (listMine != null && !listMine.isEmpty()) {
            CURRENT_PAGER = MINE_PAGER;
            return;
        }

        List<AccessibilityNodeInfo> listConstact = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(HEADER_CONTACT_ID);
        if (listConstact != null && !listConstact.isEmpty()) {
            CURRENT_PAGER = CONTACT_PAGER;
            return;
        }

        List<AccessibilityNodeInfo> listCompany = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(TAB_COMPANY_INDEX_ID);
        if (listCompany != null && !listCompany.isEmpty()) {
            CURRENT_PAGER = TCN_PAGER;
            return;
        }
        List<AccessibilityNodeInfo> listDing = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(HEADER_DING);
        if (listDing != null && !listDing.isEmpty()) {
            CURRENT_PAGER = DING_PAGER;
            return;
        }
        List<AccessibilityNodeInfo> listMessage = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(HEADER_MESSAGE);
        if (listMessage != null && !listMessage.isEmpty()) {
            CURRENT_PAGER = MESSAGE_PAGER;
            return;
        }

    }

    /*? ?*/
    private void switchMine() {
        if (STATE != STATE_CHECKED_IN)
            return;
        AccessibilityNodeInfo mAccessibilityNodeInfo = findById(HOME_MINE_ID);
        if (mAccessibilityNodeInfo == null)
            return;
        mAccessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        CURRENT_PAGER = MINE_PAGER;
    }

    /**
     * ?
     * ?
     * ?? ? ?12?
     * ??12 ??12 
     * ??
     */
    private void openCheckInDialog() {
        AccessibilityNodeInfo mAccessibilityNodeInfo = findById(WEBVIEW_PARENT);
        if (mAccessibilityNodeInfo == null)
            return;

        String date = getHourAndMin(System.currentTimeMillis());

        String[] arrayDate = date.split(":");
        int hour = Integer.parseInt(arrayDate[0]);

        if (hour > TIME_LIMIT) {

            List<AccessibilityNodeInfo> mNodeInfos = new ArrayList<>();
            recurseFindByTextToList("?", this.getRootInActiveWindow(), mNodeInfos);

            if (mNodeInfos.size() >= 2) {
                STATE = STATE_CHECKED_IN;
                mNodeInfos.clear();
                mNodeInfos = null;
                Toast.makeText(App.mContext, "??", Toast.LENGTH_SHORT).show();
                backHomePager();
                return;
            }

            AccessibilityNodeInfo mInfoAfter = recurseFindByText(AFTER_WORK, this.getRootInActiveWindow());
            if (mInfoAfter == null) {
                return;
            }
            recycle(mAccessibilityNodeInfo, AFTER_WORK, true);
        } else {

            AccessibilityNodeInfo mInfo = recurseFindByText(AFTER_WORK, this.getRootInActiveWindow());
            if (mInfo != null) {
                //                Toast.makeText(App.mContext, "??", Toast.LENGTH_SHORT).show();
                STATE = STATE_CHECKED_IN;
                backHomePager();
                return;
            }
            AccessibilityNodeInfo mInfoGo = recurseFindByText(GO_TO_WORK, this.getRootInActiveWindow());
            if (mInfoGo == null) {
                return;
            }
            recycle(mAccessibilityNodeInfo, GO_TO_WORK, true);
        }

    }

    private void backHomePager() {
        inputClick(CHECK_IN_PAGER_BACK);
        handleHomeInsensitiveCallback(tag_callback_time);
    }

    /**
     * AccessibilityNodeInfo,?
     * ? textAccessibilityNodeInfo
     *
     * @param text
     * @return
     */
    private AccessibilityNodeInfo findByText(String text) {
        AccessibilityNodeInfo mAccessibilityNodeInfo = this.getRootInActiveWindow();
        if (mAccessibilityNodeInfo == null)
            return null;
        List<AccessibilityNodeInfo> list = mAccessibilityNodeInfo.findAccessibilityNodeInfosByText(text);
        if (list == null || list.isEmpty())
            return null;
        return list.get(0);
    }

    /*?---*/
    private void openCheckInPager() {
        AccessibilityNodeInfo mAccessibilityNodeInfo = findById(RECYCLERVIEW_WORK_ID);
        if (mAccessibilityNodeInfo == null)
            return;
        recycle(mAccessibilityNodeInfo, "?", false);
    }

    /*??*/
    private boolean isCheckInPager() {

        return findById(TAB_COMPANY_INDEX_ID) != null;
    }

    private AccessibilityNodeInfo findById(String id) {
        AccessibilityNodeInfo mAccessibilityNodeInfo = this.getRootInActiveWindow();
        if (mAccessibilityNodeInfo == null)
            return null;
        List<AccessibilityNodeInfo> mNodeInfos = mAccessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);
        if (mNodeInfos == null || mNodeInfos.isEmpty())
            return null;
        return mNodeInfos.get(0);
    }

    /*???*/
    private void performWaitCheckIn() {

        AccessibilityNodeInfo mAccessibilityNodeInfo = this.getRootInActiveWindow();
        if (mAccessibilityNodeInfo == null)
            return;
        List<AccessibilityNodeInfo> mNodeInfos = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(HOME_BOTTOM_WORK_ID);
        if (mNodeInfos == null || mNodeInfos.isEmpty())
            return;
        /*?Bottom*/
        AccessibilityNodeInfo mNodeInfoBottomWork = mNodeInfos.get(0);
        if (mNodeInfoBottomWork.isClickable()) {
            mNodeInfoBottomWork.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            CURRENT_PAGER = TCN_PAGER;
        }

    }

    private KeyguardManager.KeyguardLock kl;

    private void wakeAndUnlock() {
        //???
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

        //?PowerManager.WakeLock???|??Tag
        PowerManager.WakeLock wl = pm
                .newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");

        //?
        wl.acquire(1000);

        //??
        KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        kl = km.newKeyguardLock("unLock");

        //?
        kl.disableKeyguard();

    }

    /**/
    private void toSignIn() {
        AccessibilityNodeInfo mAccessibilityNodeInfo = this.getRootInActiveWindow();
        if (mAccessibilityNodeInfo == null)
            return;
        List<AccessibilityNodeInfo> mEdPhoneNodes = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(PHONE_ID);
        if (mEdPhoneNodes == null || mEdPhoneNodes.isEmpty())
            return;
        isChecking = true;
        AccessibilityNodeInfo mEdPhoneNode = mEdPhoneNodes.get(0);
        CharSequence mCharSequence = mEdPhoneNode.getText();

        if (mCharSequence != null && !mCharSequence.toString().equals(targetCheckInAcount.getAccount())) {
            mEdPhoneNode.performAction(AccessibilityNodeInfo.ACTION_FOCUS);//?
            Rect mRect = new Rect();
            mEdPhoneNode.getBoundsInScreen(mRect);
            doShellCmdInputTap(mRect.right - 10, mRect.centerY());
            setTextToView(mEdPhoneNode, "");
            setTextToView(mEdPhoneNode, targetCheckInAcount.getAccount());
        }

        List<AccessibilityNodeInfo> mEdPasswordNodes = mAccessibilityNodeInfo
                .findAccessibilityNodeInfosByViewId(PASSWORD_ID);
        if (mEdPasswordNodes == null)
            return;
        AccessibilityNodeInfo mEdPasswordNode = mEdPasswordNodes.get(0);
        CharSequence mCharSequencePassword = mEdPasswordNode.getText();
        setTextToView(mEdPasswordNode, "");
        setTextToView(mEdPasswordNode, targetCheckInAcount.getPassword());

        /*?*/
        inputClick(BUTTON_ID);
    }

    /**
     * 
     */
    private void setTextToView(AccessibilityNodeInfo node, String text) {
        Bundle arguments = new Bundle();
        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
        arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
        node.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
        /*?*/
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Bundle args = new Bundle();
            args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
            node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args);
        } else {
            ClipData data = ClipData.newPlainText("reply", text);
            ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            clipboardManager.setPrimaryClip(data);
            node.performAction(AccessibilityNodeInfo.ACTION_FOCUS); // ?
            node.performAction(AccessibilityNodeInfo.ACTION_PASTE); // 
        }

    }

    /**
     * ID?
     *
     * @param clickId
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void inputClick(String clickId) {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(clickId);
            for (AccessibilityNodeInfo item : list) {
                item.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }

    /*??*/
    private volatile boolean isCut = false;

    private ShellUtils.CommandResult doShellCmdInputTap(int x, int y) {
        List<String> mCmds = new ArrayList<>();
        mCmds.add("input tap " + x + " " + y);
        ShellUtils.CommandResult mCommandResult = ShellUtils.execCmd(mCmds, true);

        return mCommandResult;
    }

    private void handleIt(AccessibilityNodeInfo info) {

        if (!isCut) {
            isCut = true;
            //            Toast.makeText(App.mContext, "??", Toast.LENGTH_SHORT).show();
        }
        Rect mRect = new Rect();
        info.getBoundsInScreen(mRect);
        ShellUtils.CommandResult mCommandResult = doShellCmdInputTap(mRect.centerX(), mRect.centerY());
        if (mCommandResult.result == 0) {
            STATE = STATE_CHECKED_IN;
        }

    }

    private volatile boolean isGo = true;

    private void handleGoToWork(AccessibilityNodeInfo info) {
        if (isGo) {
            isGo = false;
            //            Toast.makeText(App.mContext, "???? ... ", Toast.LENGTH_SHORT).show();
            Rect mRect = new Rect();
            info.getBoundsInScreen(mRect);
            ShellUtils.CommandResult mCommandResult = doShellCmdInputTap(mRect.centerX(), mRect.centerY());
            if (mCommandResult.result == 0) {
                STATE = STATE_CHECKED_IN;
            }
        }
    }

    /**
     * AccessibilityNodeInfo  ?webView 
     * List
     * ? ???target??
     *
     * @param target
     * @param accessibilityNodeInfo
     * @return
     */
    private void recurseFindByTextToList(String target, AccessibilityNodeInfo accessibilityNodeInfo,
            @NonNull List<AccessibilityNodeInfo> mInfos) {

        if (accessibilityNodeInfo != null && accessibilityNodeInfo.getChildCount() == 0) {

            if (((accessibilityNodeInfo.getText() != null
                    && accessibilityNodeInfo.getText().toString().contains(target))
                    || (accessibilityNodeInfo.getContentDescription() != null
                            && accessibilityNodeInfo.getContentDescription().toString().contains(target)))) {
                mInfos.add(accessibilityNodeInfo);
                return;
            } else
                return;
        } else {
            if (accessibilityNodeInfo == null)
                return;

            for (int i = 0; i < accessibilityNodeInfo.getChildCount(); i++) {
                AccessibilityNodeInfo child = accessibilityNodeInfo.getChild(i);
                recurseFindByTextToList(target, child, mInfos);
            }
            return;
        }
    }

    /**
     * AccessibilityNodeInfo  ?webView 
     *  
     *
     * @param target
     * @param accessibilityNodeInfo
     * @return
     */
    private AccessibilityNodeInfo recurseFindByText(String target, AccessibilityNodeInfo accessibilityNodeInfo) {

        if (accessibilityNodeInfo != null && accessibilityNodeInfo.getChildCount() == 0) {
            if ((target.equals(accessibilityNodeInfo.getText())
                    || target.equals(accessibilityNodeInfo.getContentDescription())))
                return accessibilityNodeInfo;
            else
                return null;
        } else {
            if (accessibilityNodeInfo == null)
                return null;

            for (int i = 0; i < accessibilityNodeInfo.getChildCount(); i++) {
                AccessibilityNodeInfo child = accessibilityNodeInfo.getChild(i);
                AccessibilityNodeInfo isTaget = recurseFindByText(target, child);
                if (isTaget == null)
                    continue;
                else
                    return isTaget;
            }
            return null;
        }
    }

    /**
     *
     */
    public void recycle(AccessibilityNodeInfo info, String target, boolean isClickSelft) {
        int temp = 0;
        if (info != null && info.getChildCount() == 0) {
            if (info.getContentDescription() != null && info.getContentDescription().toString().equals(target)
                    && isClickSelft) {

                String content = info.getContentDescription().toString();
                info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                if (content.equals(AFTER_WORK))
                    handleIt(info);
                else if (content.equals(GO_TO_WORK))
                    handleGoToWork(info);
                return;
            }
            if (info.getText() != null) {
                if (target.equals(info.getText().toString())) {
                    if (isClickSelft) {
                        info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                        return;
                    }
                    AccessibilityNodeInfo parent = info.getParent();
                    while (parent != null) {
                        if (parent.isClickable()) {
                            parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                            break;
                        }
                        parent = parent.getParent();
                    }
                }

            }
        } else {

            for (int i = 0; info != null && i < info.getChildCount(); i++) {
                if (info.getChild(i) != null) {
                    temp = i;
                    recycle(info.getChild(i), target, isClickSelft);
                }
            }
        }
    }

    /**
     * ?
     */
    @Override
    public void onInterrupt() {
        runing_monitor = false;
        isChecking = false;
    }

    /**
     * App
     *
     * @param context     
     * @param packageName ??
     */
    public static void launchApp(Context context, String packageName) {
        if ((packageName == null || packageName.trim().length() == 0))
            return;
        context.startActivity(getLaunchAppIntent(context, packageName));
    }

    /**
     * ?App?
     *
     * @param context     
     * @param packageName ??
     * @return intent
     */
    public static Intent getLaunchAppIntent(Context context, String packageName) {
        return context.getPackageManager().getLaunchIntentForPackage(packageName);
    }

    private boolean isChecking = false;

    private void doCheckIn() {

        if (isChecking) {
            return;
        }
        if (mAccountEntities == null || mAccountEntities.isEmpty() || targetCheckInAcount == null) {
            Toast.makeText(App.mContext, "", Toast.LENGTH_SHORT).show();
            return;
        }
        /*??*/
        isChecking = true;
        STATE = STATE_UNCHECKED_IN;
        //        runing_monitor = false;
        //        launchApp(this, DING_DING_PAGKET_NAME);

        List<String> mStringList = new ArrayList<>();
        /*?*/
        if (!DingHelperUtils.isScreenLight(App.mContext)) {
            mStringList.add("input keyevent 26");
            //            wakeAndUnlock();
        }
        if (DingHelperUtils.isScreenLocked(App.mContext)) {
            /*?*/
            mStringList.add("input swipe 200 800 200 100");
        }
        /*?*/
        mStringList.add("am start -n " + DING_DING_PAGKET_NAME + "/" + LOGINWINDOW);
        new OrderThread(mStringList).start();
    }

    @Override
    public void onDestroy() {
        IS_ENABLE_DINGDINGHELPERACCESSIBILITYSERVICE = false;
        stopForeground(true);
        EventBus.getDefault().unregister(this);
        isChecking = false;
        if (mHandler != null)
            mHandler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }

    private static final int NOTIFICATION_ID_PROGRESS_ID = 0x120;

    private void sendNotification(int hour, int min) {

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
        mBuilder.setSmallIcon(R.mipmap.ic_launcher);

        int lHour = 0;

        if (hour <= this.hour) {
            lHour = this.hour - hour;
        } else {
            lHour = 24 - hour + this.hour;
        }

        int lMin = 0;
        if (min <= this.min) {
            lMin = this.min - min;
        } else {
            if (this.hour != hour)
                lHour--;
            if (hour == this.hour) {
                lMin = this.min - min;
            } else
                lMin = 60 - min + this.min;
        }
        Log.i("Info", " ?:" + this.hour + ":" + this.min + " ?: " + hour + ":" + min
                + "   " + "??: " + lHour + " ?" + lMin + " ");
        mBuilder.setContentText("??: " + lHour + " ?" + lMin + " ")
                .setContentTitle("?");
        PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class),
                PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(mPendingIntent);
        NotificationManager mNotificationManager = (NotificationManager) this
                .getSystemService(NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIFICATION_ID_PROGRESS_ID, mBuilder.build());
    }

    /*???,AccessibilityService ?*/
    public static class InnerService extends Service {
        private static final void startInnerService(Context context) {
            context.startService(new Intent(context, InnerService.class));
        }

        @Override
        public void onCreate() {
            super.onCreate();
            Notification.Builder mBuilder = new Notification.Builder(this);
            mBuilder.setSmallIcon(R.mipmap.ic_launcher);
            startForeground(NOTIFICATION_ID, mBuilder.build());

            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    stopForeground(true);
                    NotificationManager mNotificationManager = (NotificationManager) InnerService.this
                            .getSystemService(NOTIFICATION_SERVICE);
                    mNotificationManager.cancel(NOTIFICATION_ID);
                    stopSelf();
                }
            }, 50);
        }

        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            stopForeground(true);
        }
    }
}