最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

教你一步步實(shí)現(xiàn)Android微信自動搶紅包

 更新時間:2016年08月28日 11:41:09   作者:oden  
自從微信添加搶紅包的功能,微信的電商之旅算是正式開始正式火爆起來。但是作為Android開發(fā)者來說,我們首先考慮的是如何實(shí)現(xiàn)Android微信自動搶紅包呢,下面我們來一起看看吧。

本文介紹微信自動搶紅包的實(shí)現(xiàn)方法,主要實(shí)現(xiàn)以下幾個功能:

      1.自動拆開屏幕上出現(xiàn)的紅包

      2.處于桌面或聊天列表時接收到紅包信息時自動進(jìn)入聊天界面并拆紅包

      3.日志功能,記錄搶紅包的詳細(xì)日志

實(shí)現(xiàn)原理

     1.利用AccessibilityService輔助服務(wù),監(jiān)測屏幕內(nèi)容,實(shí)現(xiàn)自動拆紅包的目的。

     2.利用ActiveAndroid數(shù)據(jù)庫簡單記錄紅包日志

     3.利用preference實(shí)現(xiàn)監(jiān)控選項(xiàng)紀(jì)錄

最終界面

搶紅包核心代碼

AccessibilityService配置

android:accessibilityEventTypes 設(shè)置觸發(fā)監(jiān)聽回調(diào)的事件類型;

android:packageNames 設(shè)置監(jiān)聽的應(yīng)用,這里監(jiān)聽的是微信,因此填上微信的包名com.tencent.mm

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged"
 android:accessibilityFeedbackType="feedbackGeneric"
 android:accessibilityFlags="flagDefault"
 android:canRetrieveWindowContent="true"
 android:description="@string/accessibility_description"
 android:notificationTimeout="100"
 android:packageNames="com.tencent.mm"
 android:settingsActivity="com.oden.annotations.app.activity.ManActivity" />

在AndroidManifest.xml中聲明:

 <service
   android:name=".app.service.HongbaoService_"
   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/accessibility_service_config" />
  </service>

搶紅包實(shí)現(xiàn)代碼

接收系統(tǒng)發(fā)送來的AccessibilityEvent

 private static final String GET_RED_PACKET = "領(lǐng)取紅包";
 private static final String CHECK_RED_PACKET = "查看紅包";
 private static final String RED_PACKET_PICKED = "手慢了,紅包派完了";
 private static final String RED_PACKET_PICKED2 = "手氣";
 private static final String RED_PACKET_PICKED_DETAIL = "紅包詳情";
 private static final String RED_PACKET_SAVE = "已存入零錢";
 private static final String RED_PACKET_NOTIFICATION = "[微信紅包]";

 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
  L.d("RECEIVE EVENT!");
  if (watchedFlags == null) return;
   /* 檢測通知消息 */
  if (!mMutex) {
   if (watchedFlags.get("pref_watch_notification") && watchNotifications(event)) return;
   if (watchedFlags.get("pref_watch_list") && watchList(event)) return;
  }
  if (!watchedFlags.get("pref_watch_chat")) return;

  this.rootNodeInfo = event.getSource();
  if (rootNodeInfo == null) return;

  mReceiveNode = null;
  mUnpackNode = null;

  checkNodeInfo();

   /* 如果已經(jīng)接收到紅包并且還沒有戳開 */
  if (mLuckyMoneyReceived && !mLuckyMoneyPicked && (mReceiveNode != null)) {
   mMutex = true;
   AccessibilityNodeInfo cellNode = mReceiveNode;
   cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
   mLuckyMoneyReceived = false;
   mLuckyMoneyPicked = true;
   L.d("正在打開!");
  }

   /* 如果戳開但還未領(lǐng)取 */
  if (mNeedUnpack && (mUnpackNode != null)) {
   AccessibilityNodeInfo cellNode = mUnpackNode;
   cellNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
   mNeedUnpack = false;
   L.d("正在領(lǐng)?。?);
  }

  if (mNeedBack) {
   performGlobalAction(GLOBAL_ACTION_BACK);
   mMutex = false;
   mNeedBack = false;
   L.d("正在返回!");
   //總次數(shù)和金額統(tǒng)計(jì)
   if (isGetMoney) {
    T.showShort(this, "搶到一個紅包: " + gotMoney + "元!");
    totalMoney = totalMoney + gotMoney;
    totalSuccessNum++;
    myPrefs.totalMoney().put(totalMoney);
    myPrefs.successNum().put(totalSuccessNum);
    L.d("totalMoney: " + totalMoney);
    L.d("totalSuccessNum: " + totalSuccessNum);
    saveToLog(hongbaoInfo);
    isGetMoney = false;
   }
  }
 }

檢測監(jiān)聽事件的節(jié)點(diǎn)信息

private void checkNodeInfo() {
  L.d("checkNodeInfo!");
  if (this.rootNodeInfo == null) return;
   /* 聊天會話窗口,遍歷節(jié)點(diǎn)匹配“領(lǐng)取紅包”和"查看紅包" */
  List<AccessibilityNodeInfo> nodes1 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
    GET_RED_PACKET, CHECK_RED_PACKET});
  if (!nodes1.isEmpty()) {
  L.d("!nodes1.isEmpty()");
   AccessibilityNodeInfo targetNode = nodes1.get(nodes1.size() - 1);
   if ("android.widget.LinearLayout".equals(targetNode.getParent().getClassName()))//避免被文字干擾導(dǎo)致外掛失效
   {
    if (this.signature.generateSignature(targetNode)) {
     mLuckyMoneyReceived = true;
     mReceiveNode = targetNode;
     L.d("signature:" + this.signature.toString());
    }
   } else {
    L.d("this is text");
   }
   return;
  }

  List<AccessibilityNodeInfo> nodes2 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
    "拆紅包"});
  if (!nodes2.isEmpty()) {
   L.d("node2 != null");
   for (AccessibilityNodeInfo nodeInfo : nodes2) {
     if (nodeInfo.getClassName().equals("android.widget.Button"))
      nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
   }
  } else {
    /* 戳開紅包,紅包還沒搶完,遍歷節(jié)點(diǎn)匹配“拆紅包” */
   AccessibilityNodeInfo node2 = (this.rootNodeInfo.getChildCount() > 3) ? this.rootNodeInfo.getChild(3) : null;
   if (node2 != null && node2.getClassName().equals("android.widget.Button")) {
    mUnpackNode = node2;
    mNeedUnpack = true;
    isToGetMoney = true;
    L.d("find red packet!");
    return;
   }
  }
   /* 戳開紅包,紅包已被搶完,遍歷節(jié)點(diǎn)匹配“已存入零錢”和“手慢了” */
  if (mLuckyMoneyPicked) {
   List<AccessibilityNodeInfo> nodes3 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
     RED_PACKET_PICKED, RED_PACKET_SAVE, RED_PACKET_PICKED2, RED_PACKET_PICKED_DETAIL});
   if (!nodes3.isEmpty()) {
    L.d("!nodes3.isEmpty()");    
    if (rootNodeInfo.getChildCount() > 1) {
     L.d("RED_PACKET_PICKED!");
    } else {
     L.d("nodes3.get(0).toString(): " + nodes3.get(0).getText().toString());
     if (!nodes3.get(0).getText().toString().equals(RED_PACKET_PICKED_DETAIL)) {
      AccessibilityNodeInfo targetNode = nodes3.get(nodes3.size() - 1);
      hongbaoInfo.getInfo(targetNode);
      if (isToGetMoney) {
       isGetMoney = true;
       isToGetMoney = false;
       gotMoney = hongbaoInfo.getMoney();
       L.d("gotMoney: " + gotMoney);
      }
      L.d("RED_PACKET_SAVE!");
      L.d("hongbaoInfo: " + hongbaoInfo.toString());
     } else {
      L.d("this packet is myself!");
     }

    }
    mNeedBack = true;
    mLuckyMoneyPicked = false;
   }
  }
 }

主要通過檢測“領(lǐng)取紅包”等關(guān)鍵文字信息來判斷是否有新紅包

檢測收到紅包時判斷是否"android.widget.LinearLayout",屏蔽聊天信息中的文字干擾

拆紅包時,由于微信版本可能不同,同時進(jìn)行兩種判斷,以兼容部分版本

拆完紅包需自動返回,有以下幾種情況:搶到了,手慢了,以及該紅包是自己發(fā)出的紅包

下面是監(jiān)聽聊天列表的代碼:

private boolean watchList(AccessibilityEvent event) {
  // Not a message
  if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || event.getSource() == null)
   return false;

  List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(RED_PACKET_NOTIFICATION);
  if (!nodes.isEmpty()) {
   AccessibilityNodeInfo nodeToClick = nodes.get(0);
   CharSequence contentDescription = nodeToClick.getContentDescription();
   if (contentDescription != null && !lastContentDescription.equals(contentDescription)) {
    nodeToClick.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    lastContentDescription = contentDescription.toString();
    return true;
   }
  }
  return false;
 }

下面是監(jiān)聽通知信息的代碼:

 private boolean watchNotifications(AccessibilityEvent event) {
  // Not a notification
  if (event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
   return false;

  // Not a hongbao
  String tip = event.getText().toString();
  if (!tip.contains(RED_PACKET_NOTIFICATION)) return true;

  Parcelable parcelable = event.getParcelableData();
  if (parcelable instanceof Notification) {
   Notification notification = (Notification) parcelable;
   try {
    notification.contentIntent.send();
   } catch (PendingIntent.CanceledException e) {
    e.printStackTrace();
   }
  }
  return true;
 }

紅包信息的獲取,及日志的存儲

通過獲取節(jié)點(diǎn)的子信息,分別獲得紅包發(fā)送者及搶到的金額、搶紅包時間等信息,建立簡單的表單分別記錄該信息。

@Table(name = "HongbaoInfos")
public class HongbaoInfo extends Model {

 private int month;
 private int day;
 private int hour;
 private int min;
 private int sec;

 @Column(name = "sender")
 public String sender;

 @Column(name = "money")
 public String money;

 @Column(name = "time")
 public String time;

 public void getInfo(AccessibilityNodeInfo node) {

  AccessibilityNodeInfo hongbaoNode = node.getParent();
  sender = hongbaoNode.getChild(0).getText().toString();
  money = hongbaoNode.getChild(2).getText().toString();
  time = getStringTime();
 }

 private String getStringTime() {
  Calendar c = Calendar.getInstance();
  month = c.get(Calendar.MONTH) + 1;
  day = c.get(Calendar.DAY_OF_MONTH);
  hour = c.get(Calendar.HOUR_OF_DAY);
  min = c.get(Calendar.MINUTE);
  sec = c.get(Calendar.SECOND);
  return month+"月"+day+"日 "+hour+":"+min+":"+sec;
 }

 @Override
 public String toString() {
  return "HongbaoInfo [sender=" + sender + ", money=" + money + ", time=" + time + "]";
 }

 public static List<HongbaoInfo> getAll() {
  return new Select()
    .from(HongbaoInfo.class)
    .orderBy("Id ASC")
    .execute();
 }

 public static void deleteALL() {
  new Delete().from(HongbaoInfo.class).execute();
 }

 public float getMoney() {
  return Float.parseFloat(money);
 }

 public String getSender() {
  return sender;
 }

 public String getTime() {
  return time;
 }
}

存儲操作:

 private void saveToLog(HongbaoInfo hongbaoInfo) {
  if (watchedFlags.get("pref_etc_log")) {
   HongbaoInfo hongbaoInfo1 = new HongbaoInfo();
   hongbaoInfo1 = hongbaoInfo;
   hongbaoInfo1.save();
  } else {
   L.d("log closed!");
  }
 }

總結(jié)

主要的代碼到這里基本結(jié)束,目前在微信最新版上測試ok,尚還存在以下幾個問題:

    1.同一個人連續(xù)發(fā)的不能自動搶,因?yàn)闉榱朔乐怪貜?fù)點(diǎn)擊做了過濾,同一個人的紅包搶了后不會再次點(diǎn)擊

    2.AccessibilityService開啟時間長后有時會被系統(tǒng)關(guān)掉

結(jié)束語

以上就是本文的全部內(nèi)容了,希望對大家的學(xué)習(xí)和工作能有所幫助。

相關(guān)文章

  • Android性能優(yōu)化及性能優(yōu)化工具

    Android性能優(yōu)化及性能優(yōu)化工具

    這篇文章主要給大家分享的是Android性能優(yōu)化及性能優(yōu)化工具,下面文字會圍繞Android性能優(yōu)化的相關(guān)資料詳細(xì)的展開具體內(nèi)容,需要的朋友可以參考一下,希望對大家有所幫助
    2021-11-11
  • Android?App實(shí)現(xiàn)閃屏頁廣告圖的全屏顯示實(shí)例

    Android?App實(shí)現(xiàn)閃屏頁廣告圖的全屏顯示實(shí)例

    這篇文章主要為大家介紹了Android?App實(shí)現(xiàn)閃屏頁廣告圖的全屏顯示實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Android listview的滑動沖突解決方法

    Android listview的滑動沖突解決方法

    這篇文章主要介紹了Android listview的滑動沖突解決方法的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Android自定義View原理(實(shí)戰(zhàn))

    Android自定義View原理(實(shí)戰(zhàn))

    這篇文章主要介紹了Android自定義View原理,由于Android系統(tǒng)內(nèi)置的View不滿足我們的業(yè)務(wù)需求,變產(chǎn)生了需要自定義View的原因,關(guān)于自定義詳情,需要的小伙伴可以參考下面文章具體詳情
    2022-05-05
  • Android加載對話框同時異步執(zhí)行實(shí)現(xiàn)方法

    Android加載對話框同時異步執(zhí)行實(shí)現(xiàn)方法

    Android中通過子線程連接網(wǎng)絡(luò)獲取資料,同時顯示加載進(jìn)度對話框給用戶的操作
    2012-11-11
  • android startActivityForResult的使用方法介紹

    android startActivityForResult的使用方法介紹

    android startActivityForResult的使用方法介紹,需要的朋友可以參考一下
    2013-05-05
  • 如何在Android中實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能

    如何在Android中實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能

    隨著移動端用戶越來越依賴視頻、文件下載以及大文件傳輸,斷點(diǎn)續(xù)傳作為一種有效節(jié)省帶寬和提高用戶體驗(yàn)的技術(shù)應(yīng)運(yùn)而生,本項(xiàng)目旨在實(shí)現(xiàn)一個基于?Android?的斷點(diǎn)續(xù)傳功能,需要的朋友可以參考下
    2025-04-04
  • Android 使用版本控制工具時添加忽略文件的方式(詳解)

    Android 使用版本控制工具時添加忽略文件的方式(詳解)

    下面小編就為大家?guī)硪黄狝ndroid 使用版本控制工具時添加忽略文件的方式(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Android視圖綁定viewBinding的使用介紹

    Android視圖綁定viewBinding的使用介紹

    最近這段時間在學(xué)習(xí)Kotlin,突然發(fā)現(xiàn)谷歌已經(jīng)把kotlin-android-extensions插件廢棄,目前推薦使用ViewBinding來進(jìn)行替代,接下來通過本文給大家分享Android使用ViewBinding的詳細(xì)步驟,感興趣的朋友一起學(xué)習(xí)吧
    2023-01-01
  • Android程序打包為APK的方法詳解

    Android程序打包為APK的方法詳解

    這篇文章主要介紹了Android程序打包為APK的相關(guān)知識,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-05-05

最新評論

杭锦旗| 东海县| 盐城市| 林周县| 芒康县| 吴江市| 桃园市| 高邑县| 武夷山市| 河西区| 普安县| 文成县| 清徐县| 高州市| 资阳市| 凤阳县| 元氏县| 柳林县| 德清县| 尉氏县| 卢湾区| 惠州市| 西华县| 西平县| 封丘县| 金川县| 佳木斯市| 于田县| 赤水市| 额济纳旗| 金沙县| 峨山| 霞浦县| 浮山县| 金川县| 阳朔县| 迁安市| 宝鸡市| 馆陶县| 朔州市| 房产|