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

微信自动回复功能实现

2017-09-07 15:17 1236 查看
参考:http://www.jianshu.com/p/f67e950d84f7

源码: itsMelo https://github.com/itsMelo/WcAutoReply#fork-destination-box

扩展-自动抢红包http://blog.csdn.net/qq_15796477/article/details/52130416

思路

实现AccessibilityService,重写onAccessibilityEvent(final AccessibilityEvent event),判断event对象是TYPE_NOTIFICATION_STATE_CHANGED(通知栏事件)还是TYPE_WINDOW_STATE_CHANGED(窗体状态改变事件)。

若是TYPE_NOTIFICATION_STATE_CHANGED(通知栏事件)

1.判断是否处于锁屏状态。若是,则唤醒屏幕解锁。

2.判断app是否处于前台。若是,拉起微信。1s后,设置回复文本,模拟点击发送按钮发送。若处于后台,则拉起微信。重复1,2。

相关api

1.判断是否处于锁屏状态是通过KeyguardManager的实例inKeyguardRestrictedInputMode()方法实现。

/**
* 系统是否在锁屏状态
*
* @return
*/
private boolean isScreenLocked() {
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
return keyguardManager.inKeyguardRestrictedInputMode();
}


2.唤醒屏幕并解锁

通过PowerManager.WakeLock对象实例acquire()方法唤醒屏幕,KeyguardManager.KeyguardLock对象实例的disableKeyguard()实现解锁。

private void wakeAndUnlock() {
//获取电源管理器对象
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

//获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是调试用的Tag
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");

//点亮屏幕
wl.acquire(1000);

//得到键盘锁管理器对象
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
kl = km.newKeyguardLock("unLock");

//解锁
kl.disableKeyguard();

}


3.判断app是否处于前台

原理是通过ActivityManager实例的getRunningTasks(1).get(0).topActivity()获取顶部的activity即ComponentName 对象,若ComponentName实例包名一致则在前台。

/**
* 判断指定的应用是否在前台运行
*
* @param packageName
* @return
*/
private boolean isAppForeground(String packageName) {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
String currentPackageName = cn.getPackageName();
if (!TextUtils.isEmpty(currentPackageName) && currentPackageName.equals(packageName)) {
return true;
}

return false;
}


4.调起微信

Notification notification = (Notification) event.getParcelableData();
PendingIntent pendingIntent = notification.contentIntent;

pendingIntent.send();


5.设置自动回复的文本

getRootInActiveWindow获取活动窗口根节点,遍历子节点,通过nodeInfo.getContentDescription()获取微信对应的节点。获取EditText节点,通过ClipboardManager 对象设置ClipData,即设置给剪贴板对象。并执行粘贴操作。

AccessibilityNodeInfo rootNode = getRootInActiveWindow();
for (int i = 0; i < rootNode .getChildCount(); i++) {
AccessibilityNodeInfo nodeInfo = rootNode.getChild(i);
if (nodeInfo == null) {
android.util.Log.d("maptrix", "nodeinfo = null");
continue;
}

if(nodeInfo.getContentDescription() != null){
int nindex = nodeInfo.getContentDescription().toString().indexOf(name);
int cindex = nodeInfo.getContentDescription().toString().indexOf(scontent);

if(nindex != -1){
itemNodeinfo = nodeInfo;
}
}

if ("android.widget.EditText".equals(nodeInfo.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);
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
arguments);
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
ClipData clip = ClipData.newPlainText("label", content);
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboardManager.setPrimaryClip(clip);
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);
return true;
}

}


6.发送

nodeInfo.findAccessibilityNodeInfosByText(“发送”)获取发送按钮节点,performAction(AccessibilityNodeInfo.ACTION_CLICK)执行点击事件。

/**
* 寻找窗体中的“发送”按钮,并且点击。
*/
@SuppressLint("NewApi")
private void send() {
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if (nodeInfo != null) {
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("发送");
if (list != null && list.size() > 0) {
for (AccessibilityNodeInfo n : list) {
if(n.getClassName().equals("android.widget.Button") && n.isEnabled()){
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}

} else {
List<AccessibilityNodeInfo> liste = nodeInfo
.findAccessibilityNodeInfosByText("Send");
if (liste != null && liste.size() > 0) {
for (AccessibilityNodeInfo n : liste) {
if(n.getClassName().equals("android.widget.Button") && n.isEnabled()){
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
pressBackButton();
}
}


若是TYPE_WINDOW_STATE_CHANGED(窗体状态变化事件)

1.判断event类名是否是微信的LaunchUI(即event.getClassName().toString()

Equals(“com.tencent.mm.ui.LauncherUI”))若是,则设置回复文本。

2.判断设置回复文本是否成功,成功则发送。失败,则模拟点击事件,重新设置回复文本。设置成功后发送。

3.返回系统桌面,释放键盘键对象。

case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
android.util.Log.d("maptrix", "get type window down event");
if (!hasAction) break;
itemNodeinfo = null;
String className = event.getClassName().toString();
if (className.equals("com.tencent.mm.ui.LauncherUI")) {
if (fill()) {
send();
}else {
if(itemNodeinfo != null){
itemNodeinfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (fill()) {
send();
}
back2Home();
release();
hasAction = false;
}
}, 1000);
break;
}
}
}
//bring2Front();
back2Home();
release();
hasAction = false;
break;


流程图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: