国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android基于AccessibilityService制作的釘釘自動簽到程序代碼

2019-10-22 18:11:19
字體:
來源:轉載
供稿:網友

前兩天公司開始宣布要使用阿里釘釘來簽到啦!!!~~這就意味著,我必須老老實實每天按時簽到上班下班了,這真是一個悲傷的消息,可是!!!!那么機智(lan)的我,怎么可能就這么屈服!!!阿里釘釘簽到,說到底不就是手機軟件簽到嗎?我就是干移動開發的,做一個小應用每天自動簽到不就行了:)

說干就干,首先分析一下,阿里釘釘的簽到流程:
打開阿里釘釘->廣告頁停留2S左右->進入主頁->點擊“工作”tab->點擊“簽到”模塊->進入簽到頁面(可能會再次出現廣告和對話框)->點擊簽到

我們操作手機的過程就是這樣,要實現這些點擊,很自然想起了前段時間做的微信搶紅包小應用,利用AccessibilityService服務幫助我們實現這些自動化操作。

以上是分析過程,接下來是我對這個小功能實現的具體方案思路:

將測試手機放公司并且安裝這個應用,通過我遠程的電話撥打或者短信發送到測試手機(只要能產生廣播或者信息的就行),測試手機接受到廣播信息,喚醒釘釘,進入釘釘頁面,AccessibilityService開始工作,進行一系列點擊簽到操作,結束操作后退出釘釘,簽到完成。

通過以上過程的分析我們大概要用到的知識有以下幾塊:

1.  喚醒非自己的其他第三方應用

2.  廣播

3.  AccessibilityService服務 

以下是對這三部分代碼實現:

喚醒第三方應用

package net.fenzz.dingplug;import java.util.List;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.content.pm.ResolveInfo;public class Utils { public static void openCLD(String packageName,Context context) {   PackageManager packageManager = context.getPackageManager();   PackageInfo pi = null;    try {     pi = packageManager.getPackageInfo("com.alibaba.android.rimet", 0);    } catch (NameNotFoundException e) {    }    Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);    resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);    resolveIntent.setPackage(pi.packageName);    List<ResolveInfo> apps = packageManager.queryIntentActivities(resolveIntent, 0);    ResolveInfo ri = apps.iterator().next();    if (ri != null ) {     String className = ri.activityInfo.name;     Intent intent = new Intent(Intent.ACTION_MAIN);     intent.addCategory(Intent.CATEGORY_LAUNCHER);     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    ComponentName cn = new ComponentName(packageName, className);     intent.setComponent(cn);     context.startActivity(intent);    }  } }

接受電話廣播并且喚醒釘釘:

mainifest先注冊監聽器

 <!-- 注冊監聽手機狀態 -->   <receiver android:name=".PhoneReceiver">    <intent-filter android:priority="1000" >     <action android:name="android.intent.action.PHONE_STATE" />    </intent-filter>   </receiver> 

相關權限

<!-- 讀取手機狀態的權限 -->  <uses-permission android:name="android.permission.READ_PHONE_STATE" />   <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

代碼

package net.fenzz.dingplug;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.telephony.TelephonyManager;import android.app.Service;import android.util.Log;public class PhoneReceiver extends BroadcastReceiver { private static final String TAG = "message"; private static boolean mIncomingFlag = false; private static String mIncomingNumber = null; @Override public void onReceive(Context context, Intent intent) {  // 如果是撥打電話  if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {   mIncomingFlag = false;   String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);   Log.i(TAG, "call OUT:" + phoneNumber);  } else {   // 如果是來電   TelephonyManager tManager = (TelephonyManager) context     .getSystemService(Service.TELEPHONY_SERVICE);   switch (tManager.getCallState()) {   case TelephonyManager.CALL_STATE_RINGING:    mIncomingNumber = intent.getStringExtra("incoming_number");    Log.i(TAG, "RINGING :" + mIncomingNumber);    if(mIncomingNumber!=null&&mIncomingNumber.equals(你的手機號)){     Utils.openCLD("com.alibaba.android.rimet", context);     DingService.instance.setServiceEnable();    }    break;   case TelephonyManager.CALL_STATE_OFFHOOK:    if (mIncomingFlag) {     Log.i(TAG, "incoming ACCEPT :" + mIncomingNumber);    }    break;   case TelephonyManager.CALL_STATE_IDLE:    if (mIncomingFlag) {     Log.i(TAG, "incoming IDLE");    }    break;   }  } }}

AccessibilityService服務實現:

相關權限及注冊:

<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /><service   android:name=".DingService"   android:enabled="true"   android:exported="true"   android:label="@string/app_name"   android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >   <intent-filter>    <action android:name="android.accessibilityservice.AccessibilityService" />   </intent-filter>   <meta-data    android:name="android.accessibilityservice"    android:resource="@xml/red_service_config" /> </service>

需要在res文件夾下新建一個xml文件夾里面放入一個這樣的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/accessibility_description" android:notificationTimeout="100" android:packageNames="com.alibaba.android.rimet"  />

代碼:

package net.fenzz.dingplug;import java.util.ArrayList;import java.util.List;import android.accessibilityservice.AccessibilityService;import android.util.Log;import android.view.accessibility.AccessibilityEvent;import android.view.accessibility.AccessibilityNodeInfo;import android.widget.Toast;public class DingService extends AccessibilityService { private String TAG = getClass().getSimpleName(); private boolean isFinish = false; public static DingService instance; private int index = 1; /**  * 獲取到短信通知  * 0.喚醒屏幕  * 1.打開釘釘  * 2.確保當前頁是主頁界面  * 3.找到“工作”tab并且點擊  * 4.確保到達簽到頁面  * 5.找到簽到按鈕,并且點擊  * 6.判斷簽到是否成功  *  1.成功,退出程序  *  2.失敗,返回到主頁,重新從1開始簽到  */ @Override public void onAccessibilityEvent(AccessibilityEvent event) {  // TODO Auto-generated method stub//  final int eventType = event.getEventType();   ArrayList<String> texts = new ArrayList<String>();   Log.i(TAG, "事件---->" + event.getEventType());  if(isFinish){   return;    }  AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();   if(nodeInfo == null) {    Log.w(TAG, "rootWindow為空");    return ;   }//  nodeInfo.//  System.out.println("nodeInfo"+nodeInfo);  System.out.println("index:"+index);   switch (index) {  case 1: //進入主頁    OpenHome(event.getEventType(),nodeInfo);   break;  case 2: //進入簽到頁   OpenQianDao(event.getEventType(),nodeInfo);   break;  case 3:   doQianDao(event.getEventType(),nodeInfo);   break;  default:   break;  } } private ArrayList<String> getTextList(AccessibilityNodeInfo node,ArrayList<String> textList){  if(node == null) {   Log.w(TAG, "rootWindow為空");   return null;  }  if(textList==null){   textList = new ArrayList<String>();  }  String text = node.getText().toString();   if(text!=null&&text.equals("")){    textList.add(text);   }//  node.get  return null; } private void OpenHome(int type,AccessibilityNodeInfo nodeInfo) {  if(type == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){   //判斷當前是否是釘釘主頁   List<AccessibilityNodeInfo> homeList = nodeInfo.findAccessibilityNodeInfosByText("工作");   if(!homeList.isEmpty()){    //點擊     boolean isHome = click( "工作");     System.out.println("---->"+isHome);    index = 2;    System.out.println("點擊進入主頁簽到");   }  } } private void OpenQianDao(int type,AccessibilityNodeInfo nodeInfo) {  if(type == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){   //判斷當前是否是主頁的簽到頁   List<AccessibilityNodeInfo> qianList = nodeInfo.findAccessibilityNodeInfosByText("工作");   if(!qianList.isEmpty()){     boolean ret = click( "簽到");     index = 3;     System.out.println("點擊進入簽到頁面詳情");   }//   index = ret?3:1;   } } private void doQianDao(int type,AccessibilityNodeInfo nodeInfo) {  if(type == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){   //判斷當前頁是否是簽到頁   List<AccessibilityNodeInfo> case1 = nodeInfo.findAccessibilityNodeInfosByText("開啟我的簽到之旅");   if(!case1.isEmpty()){    click("開啟我的簽到之旅");    System.out.println("點擊簽到之旅");   }   List<AccessibilityNodeInfo> case2 = nodeInfo.findAccessibilityNodeInfosByText("我知道了");   if(!case2.isEmpty()){    click("我知道了");    System.out.println("點擊我知道對話框");   }   List<AccessibilityNodeInfo> case3 = nodeInfo.findAccessibilityNodeInfosByText("簽到");   if(!case3.isEmpty()){    Toast.makeText(getApplicationContext(), "發現目標啦!!~~", 1).show();    System.out.println("發現目標啦!");    click("簽到");    isFinish = true;   }  }//  if(type == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){//   List<AccessibilityNodeInfo> case3 = nodeInfo.findAccessibilityNodeInfosByText("簽到");//   if(!case3.isEmpty()){//    Toast.makeText(getApplicationContext(), "發現目標啦!!~~", 1).show();//   }//  } } //通過文字點擊 private boolean click(String viewText){   AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();  if(nodeInfo == null) {    Log.w(TAG, "點擊失敗,rootWindow為空");    return false;  }  List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(viewText);  if(list.isEmpty()){   //沒有該文字的控件    Log.w(TAG, "點擊失敗,"+viewText+"控件列表為空");    return false;  }else{   //有該控件   //找到可點擊的父控件   AccessibilityNodeInfo view = list.get(0);   return onclick(view); //遍歷點擊  } } private boolean onclick(AccessibilityNodeInfo view){  if(view.isClickable()){   view.performAction(AccessibilityNodeInfo.ACTION_CLICK);    Log.w(TAG, "點擊成功");    return true;  }else{   AccessibilityNodeInfo parent = view.getParent();   if(parent==null){    return false;   }   onclick(parent);  }  return false; } //點擊返回按鈕事件 private void back(){   performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK); } @Override public void onInterrupt() {  // TODO Auto-generated method stub } @Override protected void onServiceConnected() {  // TODO Auto-generated method stub  super.onServiceConnected();  Log.i(TAG, "service connected!");  Toast.makeText(getApplicationContext(), "連接成功!", 1).show();  instance = this; } public void setServiceEnable(){  isFinish = false;  Toast.makeText(getApplicationContext(), "服務可用開啟!", 1).show();  index = 1; }}

以上基本是所有代碼,這個小程序中可以不用Activity組件,也可以加一個小的Activity,用來作為系統的總開關,當然也可以自動檢測時間,來判斷是否開啟服務,這樣就不用Activity了,在這個小例子中,我使用了一個小activity,就放了一個button。

項目源碼

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 田林县| 和龙市| 罗山县| 区。| 新泰市| 阿克陶县| 北宁市| 克山县| 鄂托克旗| 东乡县| 阜平县| SHOW| 武定县| 广宁县| 岱山县| 普宁市| 汝南县| 山东| 德清县| 临夏县| 黄浦区| 大足县| 图木舒克市| 秭归县| 乐都县| 南涧| 阳泉市| 德惠市| 古田县| 东乌珠穆沁旗| 隆子县| 封丘县| 金塔县| 昌邑市| 临漳县| 大邑县| 诸城市| 金溪县| 衡阳县| 姜堰市| 扶余县|