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

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

(0)

相关推荐

  • 分享Android微信红包插件

    本文实例为大家分享了Android微信红包插件,供大家参考,具体内容如下 效果图: 具体代码 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void handleWindowChange(AccessibilityNodeInfo nodeInfo) { switch (Stage.getInstance().getCurrentStage()) { case Stage.OPENING_STAGE: // 调试信息,打印TTL // Lo

  • 为Android Studio编写自定义Gradle插件的教程

    Google已经建议Android开发全部转向Android Studio开发,Android Studio 是使用gradle编译.打包的,那么问题来了,gradle可是有一堆东西...,为了彻底了解gradle,今天就来学习下如何写自己的gradle插件(当然插件源码是使用groovy写的),先看如下代码目录: 如上图所示,plugin目录是插件源码目录,sample是用来测试插件的. 1.在目录plugin/src/main/groovy/com/micky/gradle/下新建插件类My

  • Android上使用jspf插件框架的方法

    本文实例讲述了Android上使用jspf插件框架的方法.分享给大家供大家参考.具体如下: jspf (Java Simple Plugin Framework) 是一个插件框架,集成了很多 IoC 框架的概念在里面. package de.jspfdemo; import net.xeoh.plugins.base.PluginManager; import net.xeoh.plugins.base.impl.PluginManagerFactory; import net.xeoh.plu

  • 解析离线安装Eclipse的Android ADT开发插件的具体操作(图文)

    不知道大家是不是有过这样的感觉.从 https://dl-ssl.google.com/android/eclipse/很慢呢!我是教育网所以确实是很慢的.所以我想了一个办法确保可以快点安装上ADT15.当然ADT16.ADT17也是可以的.不过我还是用ADT15做演示把.(注意:不同的SDK对应的ADT版本也不同,同时在安装时要断开网络) 很熟悉把,这是Eclipse解压后的图片当然ADT是要自己下载的.我们51CTO下载哪儿也有好多的,大家自己去下载,我就不提供下载地址啦. 打开Eclips

  • Android桌面插件App Widget用法分析

    本文实例讲述了Android桌面插件App Widget用法.分享给大家供大家参考,具体如下: 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget)是微小的应用程序视图,可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新.你可以通过一个App Widget provider来发布一个Widget.可以容纳其它App Widget的应用程序组件被称为App Widget宿主.下面的截屏显示了一个音乐App Widget. appwidget 这篇文章描述了如何使用Ap

  • Android系统实现DroidPlugin插件机制

    360手机助手使用的 DroidPlugin,它是360手机助手团队在Android系统上实现了一种插件机制.它可以在无需安装.修改的情况下运行APK文件,此机制对改进大型APP的架构,实现多团队协作开发具有一定的好处. 它是一种新的插件机制,一种免安装的运行机制 github地址:https://github.com/DroidPluginTeam/DroidPlugin 参考博客:http://blog.csdn.net/hejjunlin/article/details/52124397

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

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

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

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

  • Android实现QQ抢红包插件

    又想到快要过年了,到时候还不知道群里要发好多红包,所以我将之前在网上宕的一份微信抢红包的代码修改了一下,实现了QQ抢红包!可以支持抢QQ拼手气红包,普通红包,口令红包,现在再也不怕20年单身手速的人跟我抢红包了! 先看测试效果图: 1.抢QQ口令红包  可以看见,只要红包一发出,自动填写口令并发出,帮你将红包抢到手! 2.抢QQ拼手气红包 拼手气红包也是一样,只要红包一发出,自动帮你把红包抢到手,是不是很爽的感觉? 3.抢QQ好友发送的红包 只要好友或者群里的人把红包一发出,就会第一时间让你抢到

  • APP添加CNZZ统计插件教程 Android版添加phonegap

    KeyMob移动广告平台是精准稳定的广告SDK.移动广告平台,致力于塑造国内最具有影响力的移动广告平台.主营移动广告服务,横跨IOS.Android两大平台,包含横幅.插屏.全屏.视频广告.banner等多种广告形式. 一.导入JAR包 使用Eclipse进行开发的用户,首先将下载的MobileProbe.jar解压到本地工程目录下的libs子目录里面(例如,您的工程目录为,D:workspaceXXproject,请将MobileProbe.jar放入D:workspaceXXprojectl

随机推荐