亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時間:2018年05月14日 17:08:43   作者:fenzzz  
這篇文章主要介紹了Android基于AccessibilityService制作的釘釘自動簽到程序代碼,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

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

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

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

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

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

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

2.  廣播

3.  AccessibilityService服務(wù) 

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

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

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)聽器

 <!-- 注冊監(jiān)聽手機狀態(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)限

<!-- 讀取手機狀態(tài)的權(quán)限 --> 
 <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服務(wù)實現(xiàn):

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

<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.確保當(dāng)前頁是主頁界面
  * 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){
   //判斷當(dāng)前是否是釘釘主頁
   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){
   //判斷當(dāng)前是否是主頁的簽到頁
   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){
   //判斷當(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)目標啦!!~~", 1).show();
    System.out.println("發(fā)現(xiàn)目標啦!");
    click("簽到");
    isFinish = true;
   }
  }

//  if(type == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
//   List<AccessibilityNodeInfo> case3 = nodeInfo.findAccessibilityNodeInfosByText("簽到");
//   if(!case3.isEmpty()){
//    Toast.makeText(getApplicationContext(), "發(fā)現(xiàn)目標啦!!~~", 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í)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android組件TabHost實現(xiàn)頁面中多個選項卡切換效果

    Android組件TabHost實現(xiàn)頁面中多個選項卡切換效果

    這篇文章主要為大家詳細介紹了Android組件TabHost實現(xiàn)頁面中多個選項卡切換效果的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android讀取服務(wù)器圖片的三種方法

    Android讀取服務(wù)器圖片的三種方法

    這篇文章主要為大家詳細介紹了Android讀取服務(wù)器圖片的三種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android開發(fā)手冊Chip監(jiān)聽及ChipGroup監(jiān)聽

    Android開發(fā)手冊Chip監(jiān)聽及ChipGroup監(jiān)聽

    這篇文章主要為大家介紹了Android開發(fā)手冊Chip監(jiān)聽及ChipGroup監(jiān)聽,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Android 保存文件路徑方法

    Android 保存文件路徑方法

    今天小編就為大家分享一篇Android 保存文件路徑方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • Android開發(fā)中的文件操作工具類FileUtil完整實例

    Android開發(fā)中的文件操作工具類FileUtil完整實例

    這篇文章主要介紹了Android開發(fā)中的文件操作工具類FileUtil,結(jié)合完整實例形式分析了Android文件操作的常用技巧,包括文件的獲取、遍歷、搜索、復(fù)制、刪除、判斷等功能,需要的朋友可以參考下
    2017-11-11
  • Android編程之簡單啟動畫面實現(xiàn)方法

    Android編程之簡單啟動畫面實現(xiàn)方法

    這篇文章主要介紹了Android編程之簡單啟動畫面實現(xiàn)方法,結(jié)合實例形式較為詳細的分析了開機啟動畫面的制作步驟及布局、Activity跳轉(zhuǎn)、權(quán)限控制等的相關(guān)操作技巧,需要的朋友可以參考下
    2016-11-11
  • Android學(xué)習(xí)之Flux架構(gòu)入門

    Android學(xué)習(xí)之Flux架構(gòu)入門

    Flux是Facebook在14年提出的一種Web前端架構(gòu),主要用來處理復(fù)雜的UI邏輯的一致性問題(當(dāng)時是為了解決Web頁面的消息通知問題)。接下來從其特點和使用上來介紹Flux架構(gòu)。本文主要目的是讓你對Flux的一個架構(gòu)大體面貌有個了解。
    2016-08-08
  • Flutter持久化存儲之?dāng)?shù)據(jù)庫存儲(sqflite)詳解

    Flutter持久化存儲之?dāng)?shù)據(jù)庫存儲(sqflite)詳解

    這篇文章主要給大家介紹了關(guān)于Flutter持久化存儲之?dāng)?shù)據(jù)庫存儲的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • TextView實現(xiàn)跑馬燈效果 就這么簡單!

    TextView實現(xiàn)跑馬燈效果 就這么簡單!

    TextView實現(xiàn)跑馬燈效果,就這么簡單輕松實現(xiàn),這篇文章介紹了TextView制作跑馬燈效果的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Android給通知channel靜音的方法實例

    Android給通知channel靜音的方法實例

    這篇文章主要給大家介紹了關(guān)于Android如何給通知channel靜音的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-02-02

最新評論