Android抢红包插件实现原理浅析_Android

抢红包,先看效果图~

实现自动抢红包,解决问题有两点:

一:如何实时监听发红包的事件

二:如何在红包到来的时候自动进入页面并自动点击红包

一、如何获取红包到来的事件

为了获取红包到来状态栏的变化,我们要用到一个类:Accessibility

许多Android使用者因为各种情况导致他们要以不同的方式与手机交互。
这包括了有些用户由于视力上,身体上,年龄上的问题致使他们不能看完整的屏幕或者使用触屏,也包括了无法很好接收到语音信息和提示的听力能力比较弱的用户。
Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音(这个不支持中文),触觉反馈,手势操作,轨迹球和手柄操作。

OK,了解到这一点,那么接下来就顺利点了,首先来看看Accessibility以及AccessibilityService的使用
 1.新建一个类继承AccessibilityService,并在AndroidManifest文件里注册它:

 <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<application>
<service  android:name="com.zkhb.weixinqinghongbao.service.QiangHongBaoService"
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/qianghongbao_service_config" />
   </service>
</application>

在子类QiangHongBaoService里实现几个重要的重载方法:

onServiceConnected() - 可选。系统会在成功连接上你的服务的时候调用这个方法,在这个方法里你可以做一下初始化工作,例如设备的声音震动管理,也可以调用setServiceInfo()进行配置工作。
onAccessibilityEvent() - 必须。通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。

onInterrupt() - 必须。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。
onUnbind() - 可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作。

然后在/res/xml/accessibility_service_config.xml:

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

二、主要关注点以及如何在红包到来的时候自动进入页面并自动点击红包

在onAccessibilityEvent方法中监听状态栏的变化,主要有:

AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED、

AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED、

AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 

在响应窗体以及窗体内容变化时处理相关逻辑,获取带微信消息时以下代码打开消息:

 //将微信的通知栏消息打开
    Notification notification = (Notification) event.getParcelableData();
    PendingIntent pendingIntent = notification.contentIntent;
    try {
      pendingIntent.send();
    } catch (PendingIntent.CanceledException e) {
      e.printStackTrace();
    }

具体代码网上有很多,一般都是通过:findAccessibilityNodeInfosByText、findAccessibilityNodeInfosByViewId查找文本或者资源节点进行点击操作,但新版微信开红包页面进行了处理,没有文本信息,而如果采用:

图中resouces-id这种形式就可能出现这种情况:

在了解整个核心后,获取事件不外乎就是通过文本与id判断,那么就可以将文本改为图标方式,将id改为动态id(每次显示都是随机生成),这样一来就可以提高外挂的门槛。

如何进行规避呢,目前我想的是既然开红包的页面文本和ID都有可能会变,那我们能不能找个不变的进行判断呢,考虑过后,我觉得最可能不变的地方就是开红包这个按钮的位置,也就是图中的bounds,于是在思考过后有了下面的处理: 

 for (int i = 0; i < nodeInfo.getChildCount(); i++) {
      //Log.e("TAG", "getViewIdResourceName :"+nodeInfo.getChild(i).getViewIdResourceName());
      Rect outBounds = new Rect();
      nodeInfo.getChild(i).getBoundsInScreen(outBounds);
      int left_dp = px2dip(this, 400);
      int top_dp = px2dip(this, 1035);
      int right_dp = px2dip(this, 682);
      int bottom_dp = px2dip(this, 1320);

      int left_px = dip2px(this, left_dp);
      int top_px = dip2px(this, top_dp);
      int right_px = dip2px(this, right_dp);
      int bottom_px = dip2px(this, bottom_dp);

      Rect mStandar = new Rect(left_px,top_px,right_px,bottom_px);
      if(mStandar.contains(outBounds)){
        Log.e("TAG", "outBounds.left :"+outBounds.left+";outBounds.top :"+outBounds.top+";outBounds.right :"+outBounds.right+";outBounds.bottom :"+outBounds.bottom);
        nodeInfo.getChild(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);
        break;
      }
    }

这里取的矩形区域要比按钮区域稍大点,然后判断到开红包页面按钮是否在我们预先设置的区域内,如果在,我们直接进行点击开红包操作:AccessibilityNodeInfo.ACTION_CLICK。
其他比如如何防止重复抢等细节问题,也是要处理的问题。
好了,直接放下关键代码,仅供参考:

package com.zkhb.weixinqinghongbao.service;

import java.util.Date;
import java.util.List;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import com.zkhb.weixinqinghongbao.MainActivity;
import com.zkhb.weixinqinghongbao.R;
import com.zkhb.weixinqinghongbao.entity.HongBaoInfo;
import com.zkhb.weixinqinghongbao.util.DateFormatUtils;
import com.zkhb.weixinqinghongbao.util.LogUtil;

/**
 *
 * 抢红包服务
 */
@SuppressLint("NewApi")
public class QiangHongBaoService extends AccessibilityService {

//  static final String TAG = "QiangHongBao";

  /** 微信的包名*/
  static final String WECHAT_PACKAGENAME = "com.tencent.mm";
  /** 红包消息的关键字*/
  static final String HONGBAO_TEXT_KEY = "[微信红包]";
  /** 红包消息的关键字*/
  static final String HONGBAO_TEXT_KEY1 = "微信红包";

  private static final int ENVELOPE_RETURN = 0;

  private static final String LOCK_TAG = "屏幕";

  Handler handler = new Handler();
  /** 是否在抢红包界面里*/
//  public boolean isInMM=false;
  /** 是否可以点击*/
//  public boolean ISCLICKED=false;
  /** 是否进入过拆红包界面*/
  public static boolean ISCOMINQIANGCHB=false;
  //真正的
  public static boolean ISCOMINQIANGCHB2=false;
  //真正的判断
  public static boolean ISCOMINQIANGCHB3=false;
   /** 是否来自通知栏*/
  private static boolean ISCOMNOTIFY=false;

  private PowerManager pm;
  //点亮屏幕
  private WakeLock mWakeLock;
   //解锁锁定屏幕
  private KeyguardLock keyguardLock;
  /**判断之前用户是否锁屏 */
  private static boolean islock=false;
  /**通知服务 */
  private NotificationManager n_manager;
  public void unlock(){
    if(pm==null){
      pm = (PowerManager) getApplication().getSystemService(Context.POWER_SERVICE);
    }
    boolean isScreenOn = pm.isScreenOn();//如果为true,则表示屏幕“亮”了,否则屏幕“暗”了。
    if(!isScreenOn){
      islock=true;
      KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
      keyguardLock = keyguardManager.newKeyguardLock(LOCK_TAG);
      keyguardLock.disableKeyguard();

      mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, LOCK_TAG);
      mWakeLock.acquire();
    }
  }

  public void lock(){
    if(islock){
      //释放屏幕常亮锁
      if(null != mWakeLock) {
        mWakeLock.release();
      }
      //屏幕锁定
      if(keyguardLock!=null){
        keyguardLock.reenableKeyguard();
      }
    }
  }
  @Override
  public void onAccessibilityEvent(AccessibilityEvent event) {
    final int eventType = event.getEventType();

    LogUtil.info("事件---->" + event);

    //通知栏事件
    if(eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
      unlock();
      List<CharSequence> texts = event.getText();
      if(!texts.isEmpty()) {
        for(CharSequence t : texts) {
          String text = String.valueOf(t);
          if(text.contains(HONGBAO_TEXT_KEY)) {
            ISCOMNOTIFY=true;
            ISCOMINQIANGCHB=false;
            openNotify(event);
            break;
          }
        }
      }
    } else if(eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
      unlock();
      openHongBao(event);
//      AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
//      List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText = nodeInfo.findAccessibilityNodeInfosByText("领取红包");
//      if(findAccessibilityNodeInfosByText.isEmpty()){
//       isInMM=false;
//      }else{
//       isInMM=true;
//      }
//      List<CharSequence> text = event.getText();
//      if(text.size()>=0){
//       CharSequence charSequence = text.get(0);
////        if(charSequence.equals("微信")){
////          isInMM=true;
////        }else{
////          isInMM=false;
////        }
//      }
    }else if(eventType==AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && ISCOMNOTIFY){
      unlock();
      openHongBao(event);
      List<AccessibilityNodeInfo> InfoText = getRootInActiveWindow().findAccessibilityNodeInfosByText("领取红包");
      if(!InfoText.isEmpty()){
        checkKey2();
        ISCOMNOTIFY=false;
      }
    }
  }
  /*@Override
  protected boolean onKeyEvent(KeyEvent event) {
    //return super.onKeyEvent(event);
    return true;
  }*/
  @Override
  public boolean onUnbind(Intent intent) {
    Toast.makeText(this, "断开抢红包服务", Toast.LENGTH_SHORT).show();
    ISCOMINQIANGCHB=false;
    islock=false;
    ISCOMINQIANGCHB2=false;
    ISCOMINQIANGCHB3=false;
    ISCOMNOTIFY=false;
    setNotification("已关闭抢红包小助手服务~~",Notification.FLAG_AUTO_CANCEL,"已关闭抢红包小助手服务~~~");
    return super.onUnbind(intent);
  }
  @Override
  public void onInterrupt() {
    Toast.makeText(this, "中断抢红包服务", Toast.LENGTH_SHORT).show();
  }

  @Override
  protected void onServiceConnected() {
    super.onServiceConnected();
    ISCOMINQIANGCHB=false;
    ISCOMINQIANGCHB2=false;
    ISCOMINQIANGCHB3=false;
    islock=false;
    ISCOMNOTIFY=false;

    setNotification("已开启抢红包小助手服务~~",Notification.FLAG_NO_CLEAR,"已开启抢红包小助手服务~~~");

    Toast.makeText(this, "连接抢红包服务", Toast.LENGTH_SHORT).show();
  }

  private void setNotification(String content,int flags,String title) {
    if(n_manager==null){
      n_manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
    }
    n_manager.cancelAll();
    Notification notification=new Notification(R.drawable.ic_launcher, content, System.currentTimeMillis());
//    notification.defaults |= Notification.DEFAULT_VIBRATE;
//    long[] vibrate = {0,100,200,300}; //0毫秒后开始振动,振动100毫秒后停止,再过200毫秒后再次振动300毫秒
//    notification.vibrate=vibrate;
    notification.flags |= flags; //表明在点击了通知栏中的"清除通知"后,此通知不清除,

    Intent notificationIntent = new Intent(this,MainActivity.class); //点击该通知后要跳转的Activity
    PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),0,notificationIntent,0);
    notification.setLatestEventInfo(getApplicationContext(), title, "进入微信抢红包~~", contentIntent);

    n_manager.notify(0, notification);
  }

  private void sendNotifyEvent(){
    AccessibilityManager manager= (AccessibilityManager)getSystemService(ACCESSIBILITY_SERVICE);
    if (!manager.isEnabled()) {
      return;
    }
    AccessibilityEvent event=AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
    event.setPackageName(WECHAT_PACKAGENAME);
    event.setClassName(Notification.class.getName());
    CharSequence tickerText = HONGBAO_TEXT_KEY;
    event.getText().add(tickerText);
    manager.sendAccessibilityEvent(event);
  }

  /** 打开通知栏消息*/
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private void openNotify(AccessibilityEvent event) {
    if(event.getParcelableData() == null || !(event.getParcelableData() instanceof Notification)) {
      return;
    }
    //将微信的通知栏消息打开
    Notification notification = (Notification) event.getParcelableData();
    PendingIntent pendingIntent = notification.contentIntent;
    try {
      pendingIntent.send();
    } catch (PendingIntent.CanceledException e) {
      e.printStackTrace();
    }
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private void openHongBao(AccessibilityEvent event) {
    if("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI".equals(event.getClassName())) {
      //点中了红包,下一步就是去拆红包
      ISCOMINQIANGCHB=true;
      ISCOMINQIANGCHB2=true;
      checkKey1();
    } else if("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI".equals(event.getClassName())) {
      //拆完红包后看详细的纪录界面
       LogUtil.info("事件---->com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI");
       //nonething
//     if(ISCOMINQIANGCHB){
//       ISCOMINQIANGCHB=false;
//     }
       if(ISCOMINQIANGCHB2){
         ISCOMINQIANGCHB3=true;
       }else{
         ISCOMINQIANGCHB3=false;
       }
      checkKey3();
      ISCOMINQIANGCHB=true;
      ISCOMINQIANGCHB2=false;
      performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
      if(getSharedPreferences("config", Context.MODE_PRIVATE).getBoolean("auto", false)){
        performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
      }
      lock();
    } else if("com.tencent.mm.ui.LauncherUI".equals(event.getClassName())) {
//     isInMM=true;
      //在聊天界面,去点中红包
      LogUtil.info("事件---->com.tencent.mm.ui.LauncherUI");
      checkKey2();
    }
  }
  @SuppressLint("NewApi") @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private void checkKey3() {
    AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
     if(nodeInfo == null) {
       LogUtil.info("rootWindow为空333");
       return;
     }
     //TODO
     List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText = nodeInfo.findAccessibilityNodeInfosByText("元");
     if(findAccessibilityNodeInfosByText.size()>=0){
       AccessibilityNodeInfo accessibilityNodeInfo2 = findAccessibilityNodeInfosByText.get(0).getParent();
       CharSequence money = accessibilityNodeInfo2.getChild(2).getText();
       CharSequence name = accessibilityNodeInfo2.getChild(0).getText();
       if(ISCOMINQIANGCHB3){
         HongBaoInfo info=new HongBaoInfo();
         info.setStrDateTime(DateFormatUtils.format("yyyy-MM-dd HH:mm:ss", new Date()));
         info.setStrMoney(money+"");
         info.setStrName(name+"");
         info.save();
       }
       Toast.makeText(getApplicationContext(), money+":::"+name, 0).show();
     }
//    List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aw8");
//    AccessibilityNodeInfo accessibilityNodeInfo = findAccessibilityNodeInfosByViewId.get(0);
//    CharSequence text = accessibilityNodeInfo.getText();
  }

  private void checkKey1() {
    AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
    if(nodeInfo == null) {
      LogUtil.info("rootWindow为空11111");
      return;
    }

    for (int i = 0; i < nodeInfo.getChildCount(); i++) {
      Log.e("TAG", "getViewIdResourceName :"+nodeInfo.getChild(i).getViewIdResourceName());
      Rect outBounds = new Rect();
      nodeInfo.getChild(i).getBoundsInScreen(outBounds);
      int left_dp = px2dip(this, 400);
      int top_dp = px2dip(this, 1035);
      int right_dp = px2dip(this, 682);
      int bottom_dp = px2dip(this, 1320);

      int left_px = dip2px(this, left_dp);
      int top_px = dip2px(this, top_dp);
      int right_px = dip2px(this, right_dp);
      int bottom_px = dip2px(this, bottom_dp);

      Rect mStandar = new Rect(left_px,top_px,right_px,bottom_px);
      if(mStandar.contains(outBounds)){
        Log.e("TAG", "outBounds.left :"+outBounds.left+";outBounds.top :"+outBounds.top+";outBounds.right :"+outBounds.right+";outBounds.bottom :"+outBounds.bottom);
        nodeInfo.getChild(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);
        break;
      }
//     nodeInfo.performAction(action)//[405,1042][675,1312]
    }
    //List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("拆红包");

// List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/b5d");
//    for(AccessibilityNodeInfo n : list) {
//      n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//    }
  }

  private void checkKey2() {
    AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
    if(nodeInfo == null) {
      LogUtil.info("rootWindow为空222222");
      return;
    }
    List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("领取红包");
    if(list.isEmpty()) {
      list = nodeInfo.findAccessibilityNodeInfosByText(HONGBAO_TEXT_KEY);
      for(AccessibilityNodeInfo n : list) {
        LogUtil.info("-->微信红包:" + n);
        n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        break;
      }
    } else {
      //最新的红包领起
      AccessibilityNodeInfo parent = list.get(list.size() - 1).getParent();
//     Log.w(TAG, "ISCLICKED::"+ISCLICKED)!ISCLICKED;
      if(parent != null && !ISCOMINQIANGCHB) {
        parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
      }
//      for(int i = list.size() - 1; i >= 0; i --) {
//        AccessibilityNodeInfo parent = list.get(i).getParent();
//        Log.i(TAG, "-->领取红包:" + parent);
//        if(parent != null && parent.isClickable()) {
//          parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//          break;
//        }
//      }
//      performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
    }
  }
  /**
   * @param info 当前节点
   * @param matchFlag 需要匹配的文字
   * @param type 操作的类型
   */
  @SuppressLint("NewApi")
  public void recycle(AccessibilityNodeInfo info, String matchFlag, int type) {
    if (info != null) {
      if (info.getChildCount() == 0) {
        CharSequence desrc = info.getContentDescription();
        switch (type) {
          case ENVELOPE_RETURN://返回
            if (desrc != null && matchFlag.equals(info.getContentDescription().toString().trim())) {
              if (info.isCheckable()) {
                info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
              } else {
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
              }
            }
            break;
        }
      } else {
        int size = info.getChildCount();
        for (int i = 0; i < size; i++) {
          AccessibilityNodeInfo childInfo = info.getChild(i);
          if (childInfo != null) {
            LogUtil.info("index: " + i + " info" + childInfo.getClassName() + " : " + childInfo.getContentDescription()+" : "+info.getText());
            recycle(childInfo, matchFlag, type);
          }
        }
      }
    }
  }
  @Override
  public void onDestroy() {
    super.onDestroy();
    lock();
  }
  /**
   * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
   */
  public static int dip2px(Context context, float dpValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
  } 

  /**
   * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
   */
  public static int px2dip(Context context, float pxValue) {
//    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (pxValue / 3 + 0.5f); //3是本人手机的设备密度
  }
}

AccessibilityService还可以用在智能安装、虚拟按键上都有很多应用,这样的实践只是给我们一种解决问题另外的一种思路,问题嘛,总还是要解决的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索Android抢红包
Android抢红包插件
qq抢红包源码实现原理、微信抢红包实现原理、微信 抢红包插件 原理、抢红包实现原理、ios抢红包实现原理,以便于您获取更多的相关知识。

时间: 2024-08-29 15:19:29

Android抢红包插件实现原理浅析_Android的相关文章

Android抢红包插件实现原理浅析

抢红包,先看效果图~ 实现自动抢红包,解决问题有两点: 一:如何实时监听发红包的事件 二:如何在红包到来的时候自动进入页面并自动点击红包 一.如何获取红包到来的事件 为了获取红包到来状态栏的变化,我们要用到一个类:Accessibility 许多Android使用者因为各种情况导致他们要以不同的方式与手机交互. 这包括了有些用户由于视力上,身体上,年龄上的问题致使他们不能看完整的屏幕或者使用触屏,也包括了无法很好接收到语音信息和提示的听力能力比较弱的用户. Android提供了Accessibi

Android微信自动抢红包插件优化和实现_Android

又是兴趣系列 网上有很多自动强红包的例子和代码,笔者也是做了一些优化. 先说说自己的两个个优势 1.可以在聊天界面自动强不依赖于通知栏推送 2.可以在屏幕熄灭的时候的时候点亮屏幕自动抢(目前只测过flyme) 先上图: 代码传送门: https://github.com/AndroidMsky/WXhongbao 欢迎点星星~ 原理: 通过AccessibilityService监听到状态栏通知,进行模拟点击,获取屏幕中view节点为领取红包的list并且点击最后一个. 如果不通过状态栏通知,通

Android Handler 机制实现原理分析_Android

handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段.使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息.但是,有没有人想过这种技术是怎么实现的呢?下面我们一起探讨下. 先上图,让大家好理解下handler机制:                                                                 handler机制示例图 上面一共出现了几种类,ActivityThread

Android的支付密码输入框实现浅析_Android

先看一下效果图 实现思路: 变成点的控件不是TextView和EditText而是Imageview.首先写一个RelativeLayout里边包含6个ImageView和一个EditText(EditText要覆盖ImageView)将EditText的背景设置成透明. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas

Android中微信抢红包插件原理解析及开发思路_Android

一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导致了.或许是网络的原因,而且这个也是最大的原因.但是其他的不可忽略的因素也是要考虑到进去的,比如在手机充电锁屏的时候,我们并不知道有人已经开始发红包了,那么这时候也是让我们丧失了一大批红包的原因.那么关于网络的问题,我们开发者可能用相关技术无法解决(当然在Google和Facebook看来的话,他们

Android AccessibilityService实现微信抢红包插件_Android

在你的手机更多设置或者高级设置中,我们会发现有个无障碍的功能,很多人不知道这个功能具体是干嘛的,其实这个功能是为了增强用户界面以帮助残障人士,或者可能暂时无法与设备充分交互的人们 它的具体实现是通过AccessibilityService服务运行在后台中,通过AccessibilityEvent接收指定事件的回调.这样的事件表示用户在界面中的一些状态转换,例如:焦点改变了,一个按钮被点击,等等.这样的服务可以选择请求活动窗口的内容的能力.简单的说AccessibilityService就是一个后

Android中微信抢红包插件原理解析及开发思路

一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导致了.或许是网络的原因,而且这个也是最大的原因.但是其他的不可忽略的因素也是要考虑到进去的,比如在手机充电锁屏的时候,我们并不知道有人已经开始发红包了,那么这时候也是让我们丧失了一大批红包的原因.那么关于网络的问题,我们开发者可能用相关技术无法解决(当然在Google和Facebook看来的话,他们

Android微信抢红包功能的实现原理浅析

快到过农历年了,微信红包也越来越多了,出现了好多红包外挂程序,就很好奇如何实现的,于是自己研究了一番,亲自写了个微信抢红包的APP.现在就一步一步来实现它. 实现思路 微信抢红包程序开启时候,他就可以随时识别.捕获红包,服务可以实现正在功能,当我们开启服务的时候,服务就不停的在后台运行,不停地轮询着微信里面的消息,当发现红包时候就立即打开微信红包所在的界面.但是他怎识别红包呢?需要找到微信抢红包里面节点的view,当找到对应的view,在获取view的关键字或者id,根据关键字或者id,自动的模

Android微信自动抢红包插件优化和实现

又是兴趣系列 网上有很多自动强红包的例子和代码,笔者也是做了一些优化. 先说说自己的两个个优势 1.可以在聊天界面自动强不依赖于通知栏推送 2.可以在屏幕熄灭的时候的时候点亮屏幕自动抢(目前只测过flyme) 先上图: 代码传送门: https://github.com/AndroidMsky/WXhongbao 欢迎点星星~ 原理: 通过AccessibilityService监听到状态栏通知,进行模拟点击,获取屏幕中view节点为领取红包的list并且点击最后一个. 如果不通过状态栏通知,通