您的位置:首页 > 移动开发 > Android开发

android 利用accessibilityservice 实现自动发红包功能 (让收红包的人手抽筋)(密码不能自动输入,可以开启指纹支付)

2017-10-18 16:04 1051 查看

       简介

AccessibilityService是一个辅助类,可以监听我们手机的焦点,窗口变化,按钮点击,消息通知,文本内容等等。实现它的服务需要在手机设置里面->辅助功能(无障碍)在这里面找到你自己实现的服务;简单的说AccessibilityService就是一个后台监控服务,当你监控的内容发生改变时,就会调用后台服务的回调方法怎么使用 ?1.1创建自己的类                                                                                                                                                                                                                   新建类 继承AccessibilityService,重写onAccessibilityEvent(AccessibilityEventaccessibilityEvent)方法,onServiceConnected()方法和onInterrupt()方法。

1.2 声明服务   

<service android:name="com.hqc.sendhongbao.MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="自动发红包">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />

</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config"/>
</service>
   

1.3 配置参数

  配置参数是指:配置用来接受指定类型的事件,指定反馈类型,监听指定package,检索窗口内容,获取事件类型的超时时间,服务描述等。其配置服务参数有两种方法:1.通过meta-data标签指定xml文件进行配置
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeViewClicked"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm"/>
下面是对xml参数的介绍 copy。。。accessibilityEventTypes:表示该服务对界面中的哪些变化感兴趣,即哪些事件通知,比如窗口打开,滑动,焦点变化,长按等。具体的值可以在AccessibilityEvent类中查到,如typeAllMask表示接受所有的事件通知,accessibilityFeedbackType:表示反馈方式,比如是语音播放,还是震动canRetrieveWindowContent:表示该服务能否访问活动窗口中的内容。也就是如果你希望在服务中获取窗体内容,则需要设置其值为truedescription:对该无障碍功能的描述,在无障碍服务中显示,让用户了解该服务的功notificationTimeout:接受事件的时间间隔,通常将其设置为100即可packageNames:表示对该服务是用来监听哪个包的产生的事件,这里以微信的包名为例2. 服务类的代码 进行代码设置 , 忽略

1.4 处理事件回调信息

   
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
AccessibilityNodeInfo source = accessibilityEvent.getSource();
if (source == null) {return;}
int eventType = accessibilityEvent.getEventType();
switch (eventType) {
case AccessibilityEvent.TYPE_VIEW_CLICKED:
CharSequence des = source.getContentDescription();
// 这里监听微信的 +号。作为触发条件
if (des != null && des.equals("更多功能按钮,已展开")) {
Log.d(TAG_RESLUT, "更多功能按钮,已展开");
//找到 当前窗口的 布局。。
AccessibilityNodeInfo window = getRootInActiveWindow();
//找到红包字符,模拟点击事件。注意这里的红包本身不带点击,能点击是他的 父布局
List<AccessibilityNodeInfo> hbInfos = window.findAccessibilityNodeInfosByText("红包");
ClickParent(hbInfos, "红包");
// 红包页面 打开了标识
hbUiopened = true;
}
break;
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
CharSequence desWindow = source.getContentDescription();
CharSequence className = source.getClassName();
// 这里有个问题 ,进入红包页面,时候有个进度条页面,使用dialog完成的。每次getRootInActiveWindow()获取到的
//是 进度条那个窗口的 布局。导致无法找到 对应的按钮,解决办法。模拟历史任务按键。再次返回到当前页面 能获取正确的window
// 其他手机 可能没这个问题,因手机而不同
if (hbUiopened && desWindow != null && desWindow.equals("当前所在页面,发红包")) {//首次进入发红包页面。window为进度条页面
Log.d(TAG_RESLUT, "当前所在页面,发红包");
performGlobalAction(AccessibilityService.GLOBAL_ACTION_RECENTS);
//定时器
Message message = handler.obtainMessage();
message.what = COME_IN_HB_UI;
// 1秒后 再次模拟 历史任务键 返回到当前页面, 太快了。还在 进度条页面
message.getTarget().sendMessageDelayed(message, 1000);
return;
}
if (isInHbUi) { //到红包页面了
AccessibilityNodeInfo window = getRootInActiveWindow();
if (window == null) {
Log.d("window is  null", "11");
return;
}
//  t替换 moeny
findNodeByTextAndSetNewValue(window, "0.00", String.valueOf(hbMoney));

if(!TextUtils.isEmpty(msg)){
// 替换 留言
findNodeByTextAndSetNewValue(window, "恭喜发财,大吉大利", msg);
}

List<AccessibilityNodeInfo> hbInfos = window.findAccessibilityNodeInfosByText("塞钱进红包");
ClickParent(hbInfos, "塞钱进红包");
isInHbUi = false;
isInPayUi = true;
return;
}
if (TextUtils.isEmpty(desWindow)) {
return;
}

String windowStr = desWindow.toString();
// 检测 是否回到了  聊天页面
if (isInPayUi && windowStr != null && windowStr.contains("当前所在页面,") && windowStr.contains("聊天")) {//回到了 聊天页面
isInPayUi = false;
realNum++;
if(realNum== hbNum){//发送完毕
stopSelf();
return;
}
//再次模拟  点击红包事件
AccessibilityNodeInfo window = getRootInActiveWindow();
List<AccessibilityNodeInfo> hbInfos = window.findAccessibilityNodeInfosByText("红包");
ClickParent(hbInfos, "红包");
hbUiopened = true;
}
break;
}
}
// 替黄文字。。。 可以根据 findAccessibilityNodeInfosByText 找到对应的  nodeinfo,但有时候可能找不到,
//可以做 window的遍历
public void findNodeByTextAndSetNewValue(AccessibilityNodeInfo info, String text, String newValue) {

if (info.getChildCount() == 0 && text != null && text.equals(info.getText())) {

if ("android.widget.EditText".equals(info.getClassName())) {
Bundle arguments = new Bundle();
arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
true);
info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
arguments);
info.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
ClipData clip = ClipData.newPlainText("label", newValue);
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboardManager.setPrimaryClip(clip);
info.performAction(AccessibilityNodeInfo.ACTION_PASTE);
}

return;
} else {
for (int i = 0; i < info.getChildCount(); i++) {
if (info.getChild(i) != null) {
findNodeByTextAndSetNewValue(info.getChild(i), text, newValue);
}
}
}
}
//  模拟点击 事件,有可能你找到的 控件,不支持点击,只能向上 到父级 实现, fitle 控件名字,过滤掉其他的不需要的控件
// 比如你 根据  红包 找到 很多个可以点击的控件, 容易误操作 findAccessibilityNodeInfosByText方法 返回的是包含关系的
// 你 红包 关键字,返回的 拆红包, 领取红包 微信红包 等
private void ClickParent(List<AccessibilityNodeInfo> infos, String fitle) {
if (infos == null) {
return;
}
for (AccessibilityNodeInfo info : infos) {
if (!info.isEnabled() || info.getText() == null || !info.getText().equals(fitle)) {
continue;
}
if (info.isClickable()) {
info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
} else {
AccessibilityNodeInfo parent = info.getParent();
while (parent != null) {
if (parent.isClickable()) {
parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
break;
}
parent = parent.getParent();
}
}

}
}
// hand  定时
private static final int COME_IN_HB_UI = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case COME_IN_HB_UI:
performGlobalAction(AccessibilityService.GLOBAL_ACTION_RECENTS);
//加载完成
hbUiopened = false;
isInHbUi = true;
break;
}
}
};
注意,因为微信特殊处理,支付那个页面,不能模拟。故此只能手动输入,或者使用 指纹支付1.5 其他             是否安装该服务?注意 serviceName = 包名+类全名 或者 报名/.类名 
String serviceName = getPackageName() + "/.MyAccessibilityService";
AccessibilityManager am = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);boolean isInstall=false;List<AccessibilityServiceInfo> installedAccessibilityServiceList = am.getInstalledAccessibilityServiceList();for (AccessibilityServiceInfo info : installedAccessibilityServiceList) {Log.d("MainActivity", "all -->" + info.getId());if (serviceName.equals(info.getId())) {isInstall=true;break;}}
   是否启用该服务?
List<AccessibilityServiceInfo> serviceInfos = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);for (AccessibilityServiceInfo info : serviceInfos) {Log.d("MainActivity", "use -->" + info.getId());if (serviceName.equals(info.getId())) {isUse = true;break;}}
     跳转到设置页面 开启服务,只能跳转到页面,不能强制开启
/*** 跳转到系统设置页面开启辅助功能*/private void openAccessibility(){Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);startActivity(intent);}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐