激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Android - Android基于AccessibilityService制作的釘釘自動簽到程序代碼

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

2022-02-20 15:26fenzzz Android

這篇文章主要介紹了Android基于AccessibilityService制作的釘釘自動簽到程序代碼,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

說干就干,首先分析一下,阿里釘釘?shù)暮灥搅鞒蹋?br /> 打開阿里釘釘->廣告頁停留2S左右->進(jìn)入主頁->點擊“工作”tab->點擊“簽到”模塊->進(jìn)入簽到頁面(可能會再次出現(xiàn)廣告和對話框)->點擊簽到

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

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

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

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

1.  喚醒非自己的其他第三方應(yīng)用

2.  廣播

3.  AccessibilityService服務(wù) 

以下是對這三部分代碼實現(xiàn):

喚醒第三方應(yīng)用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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先注冊監(jiān)聽器

?
1
2
3
4
5
6
<!-- 注冊監(jiān)聽手機(jī)狀態(tài) -->
 <receiver android:name=".PhoneReceiver">
  <intent-filter android:priority="1000" >
   <action android:name="android.intent.action.PHONE_STATE" />
  </intent-filter>
 </receiver>

相關(guān)權(quán)限

?
1
2
3
<!-- 讀取手機(jī)狀態(tài)的權(quán)限 -->
 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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(你的手機(jī)號)){
     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服務(wù)實現(xiàn):

相關(guān)權(quán)限及注冊:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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配置文件:

?
1
2
3
4
5
6
7
8
9
10
<?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"
 />

代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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.確保當(dāng)前頁是主頁界面
  * 3.找到“工作”tab并且點擊
  * 4.確保到達(dá)簽到頁面
  * 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: //進(jìn)入主頁
    OpenHome(event.getEventType(),nodeInfo);
   break;
  case 2: //進(jìn)入簽到頁
   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){
   //判斷當(dāng)前是否是釘釘主頁
   List<AccessibilityNodeInfo> homeList = nodeInfo.findAccessibilityNodeInfosByText("工作");
   if(!homeList.isEmpty()){
    //點擊
     boolean isHome = click( "工作");
     System.out.println("---->"+isHome);
    index = 2;
    System.out.println("點擊進(jìn)入主頁簽到");
   }
  }
 }
 private void OpenQianDao(int type,AccessibilityNodeInfo nodeInfo) {
  if(type == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){
   //判斷當(dāng)前是否是主頁的簽到頁
   List<AccessibilityNodeInfo> qianList = nodeInfo.findAccessibilityNodeInfosByText("工作");
   if(!qianList.isEmpty()){
     boolean ret = click( "簽到");
     index = 3;
     System.out.println("點擊進(jìn)入簽到頁面詳情");
   }
 
//   index = ret?3:1;
  }
 }
 private void doQianDao(int type,AccessibilityNodeInfo nodeInfo) {
  if(type == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){
   //判斷當(dāng)前頁是否是簽到頁
   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(), "發(fā)現(xiàn)目標(biāo)啦??!~~", 1).show();
    System.out.println("發(fā)現(xiàn)目標(biāo)啦!");
    click("簽到");
    isFinish = true;
   }
  }
 
//  if(type == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
//   List<AccessibilityNodeInfo> case3 = nodeInfo.findAccessibilityNodeInfosByText("簽到");
//   if(!case3.isEmpty()){
//    Toast.makeText(getApplicationContext(), "發(fā)現(xiàn)目標(biāo)啦!!~~", 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(), "服務(wù)可用開啟!", 1).show();
  index = 1;
 }
}

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

項目源碼

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/fenzzz/article/details/50156697

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一本色道久久综合狠狠躁篇适合什么人看 | 老女人碰碰在线碰碰视频 | 国产伊人色 | 韩国十九禁高潮床戏在线观看 | 中国免费黄色 | 久草资源在线观看 | 精品国产一区二区三区在线观看 | 黄色免费av网站 | 成年免费网站 | 伦一区二区三区中文字幕v亚洲 | www.99久 | 成人在线观看一区 | 国产精品视频免费在线观看 | 亚洲午夜一区二区三区 | 爱视频福利 | 在线成人一区 | 欧美一区二区片 | 毛片网站视频 | 久久久日韩精品一区二区三区 | 欧美亚洲国产成人 | 中文字幕偷拍 | 激情亚洲一区二区三区 | 欧美黄成人免费网站大全 | 久久观看免费视频 | 九九热在线视频免费观看 | xxxxhdhdhdhd日本 | 亚洲αv | 91午夜视频 | 免费看综艺策驰影院 | 在线区 | 深夜福利视频绿巨人视频在线观看 | 国产成人视屏 | 男女羞羞视频在线免费观看 | 欧美成人免费在线视频 | 免费视频xxxx| 黄色片网站在线免费观看 | 久久久鲁 | 国产一区网址 | 手机在线看片国产 | 精品一二三区视频 | 牛牛视频在线 |