fix fucking accessibility service

This commit is contained in:
hyb1996
2017-07-16 10:19:07 +08:00
parent fcf46c49de
commit 73773faedc
13 changed files with 186 additions and 69 deletions

View File

@@ -9,8 +9,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 147 versionCode 148
versionName "2.0.14 Beta" versionName "2.0.14 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -3,27 +3,30 @@
var 好友验证信息 = "AutoJs自动添加群好友"; var 好友验证信息 = "AutoJs自动添加群好友";
var 延迟 = 500; var 延迟 = 500;
toast("请打开群成员列表"); launchApp("QQ");
toast("请打开要加的群");
sleep(500);
if(currentActivity() != "com.tencent.mobileqq.activity.TroopMemberListActivity"){
openGroupMemberList();
}
var added = {}; var added = {};
while(true){ while(true){
var list = className("AbsListView").findOne(); var list = className("AbsListView").findOne();
list.children().each(function(child){ var count = list.childCount();
if(child.className() != "android.widget.FrameLayout"){ for(var i = 0; i < count; i++){
return; var child = list.child(i);
} if(!child || child.className() != "android.widget.FrameLayout"){
if(!isGroupMember(child)){ continue;
return; }
} if(!isGroupMember(child) || isMyself(child)){
if(isMyself(child)){ continue;
return; }
} child.child(0).click();
child.child(0).click(); sleep(500);
sleep(500); addAsFriend();
addAsFriend(); sleep(延迟);
sleep(延迟); }
});
className("AbsListView").findOne().scrollForward();
} }
@@ -31,6 +34,9 @@ function isGroupMember(child){
if(child.childCount() != 1){ if(child.childCount() != 1){
return false; return false;
} }
if(!child.findByText("Baby Q").isEmpty()){
return false;
}
return child.child(0) && child.child(0).className() == "android.widget.FrameLayout"; return child.child(0) && child.child(0).className() == "android.widget.FrameLayout";
} }
@@ -41,6 +47,7 @@ function isMyself(child){
function addAsFriend(){ function addAsFriend(){
var qq = getQQ(); var qq = getQQ();
toast(qq);
if(added[qq]){ if(added[qq]){
while(!click("返回")); while(!click("返回"));
return; return;
@@ -64,3 +71,11 @@ function getQQ(){
var qq = textMatches("\\d{5,12}").findOne().text(); var qq = textMatches("\\d{5,12}").findOne().text();
return qq; return qq;
} }
function openGroupMemberList(){
desc("群资料卡").click();
var groupMemberCountView = textEndsWith("名成员").findOne();
var groupMemberCount = parseInt(/\d+/.exec(groupMemberCountView.text())[0]);
groupMemberCountView.parent().click();
sleep(groupMemberCount * 4);
}

View File

@@ -24,11 +24,13 @@ sleep(100);
waitForActivity("com.tencent.mobileqq.activity.VisitorsActivity"); waitForActivity("com.tencent.mobileqq.activity.VisitorsActivity");
while(notStopped()){ while(notStopped()){
var i = 0; var i = 0;
while(i < 10){ while(i < 10){
i += () ? 1 : 0; i += () ? 1 : 0;
click("取消"); click("取消");
} }
显示更多(); 显示更多();
下滑(); if(currentActivity() == "com.tencent.mobileqq.activity.VisitorsActivity"){
下滑();
}
} }

View File

@@ -0,0 +1,21 @@
"auto";
toast("请打开自己的资料页,点击点赞图标");
sleep(500);
waitForActivity("com.tencent.mobileqq.activity.VisitorsActivity");
while(notStopped()){
for(var i = 0; i < 10; i++){
className("ImageView").desc("赞").untilFind().each(function(like){
var parent = like.parent();
if(like.parent().findByText("(好友)")){
like.click();
}
});
}
click("显示更多");
click("显示更多");
if(currentActivity() == "com.tencent.mobileqq.activity.VisitorsActivity"){
className("AbsListView").scrollable().scrollForward();
}
}

View File

@@ -1,24 +1,32 @@
"auto"; "auto";
var liked = {};
launchApp("QQ");
toast("请打开要点赞的群");
sleep(500);
if(currentActivity() != "com.tencent.mobileqq.activity.TroopMemberListActivity"){
openGroupMemberList();
}
while(true){ while(true){
var list = className("AbsListView").findOne(); var list = className("AbsListView").findOne();
list.children().each(function(child){ var count = list.childCount();
if(child.className() != "android.widget.FrameLayout"){ for(var i = 0; i < count; i++){
return; var child = list.child(i);
} if(!child || child.className() != "android.widget.FrameLayout"){
if(!isGroupMember(child)){ continue;
return; }
} if(!isGroupMember(child) || isMyself(child)){
if(isMyself(child)){ continue;
return; }
} child.child(0).click();
child.child(0).click(); sleep(500);
like(); like();
while(!click("返回")); while(!click("返回"));
while(!click("成员资料")); while(!click("成员资料"));
while(!click("返回")); while(!click("返回"));
}); sleep(500);
className("AbsListView").findOne().scrollForward(); }
list.scrollForward();
} }
@@ -26,6 +34,9 @@ function isGroupMember(child){
if(child.childCount() != 1){ if(child.childCount() != 1){
return false; return false;
} }
if(!child.findByText("Baby Q").isEmpty()){
return false;
}
return child.child(0) && child.child(0).className() == "android.widget.FrameLayout"; return child.child(0) && child.child(0).className() == "android.widget.FrameLayout";
} }
@@ -35,11 +46,6 @@ function isMyself(child){
} }
function like(){ function like(){
var qq = getQQ();
if(liked[qq]){
while(!click("返回"));
return;
}
while(!click("更多")); while(!click("更多"));
while(!click("查看个人资料卡")); while(!click("查看个人资料卡"));
var likeBtn = descEndsWith("点击可赞").findOne(); var likeBtn = descEndsWith("点击可赞").findOne();
@@ -53,3 +59,11 @@ function getQQ(){
var qq = textMatches("\\d{5,12}").findOne().text(); var qq = textMatches("\\d{5,12}").findOne().text();
return qq; return qq;
} }
function openGroupMemberList(){
desc("群资料卡").click();
var groupMemberCountView = textEndsWith("名成员").findOne();
var groupMemberCount = parseInt(/\d+/.exec(groupMemberCountView.text())[0]);
groupMemberCountView.parent().click();
sleep(groupMemberCount * 4);
}

View File

@@ -30,7 +30,12 @@ public class HoverMenuManger {
if (!HoverMenuService.isServiceRunning()) { if (!HoverMenuService.isServiceRunning()) {
if (!SettingsCompat.canDrawOverlays(App.getApp())) { if (!SettingsCompat.canDrawOverlays(App.getApp())) {
Toast.makeText(App.getApp(), R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show(); Toast.makeText(App.getApp(), R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show();
SettingsCompat.manageDrawOverlays(App.getApp()); try {
SettingsCompat.manageDrawOverlays(App.getApp());
} catch (Exception e) {
e.printStackTrace();
IntentUtil.goToAppDetailSettings(App.getApp());
}
} else { } else {
HoverMenuService.startService(App.getApp()); HoverMenuService.startService(App.getApp());
} }

View File

@@ -22,6 +22,7 @@ import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayout
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.theme.ThemeColorManagerCompat; import com.stardust.theme.ThemeColorManagerCompat;
import com.stardust.util.IntentUtil;
import com.stardust.util.MessageEvent; import com.stardust.util.MessageEvent;
import com.stardust.util.MessageIntent; import com.stardust.util.MessageIntent;
@@ -129,7 +130,12 @@ public class HoverMenuService extends Service {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Toast.makeText(this, R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show();
SettingsCompat.manageDrawOverlays(this); try {
SettingsCompat.manageDrawOverlays(this);
} catch (Exception ex) {
ex.printStackTrace();
IntentUtil.goToAppDetailSettings(this);
}
} }
} }

View File

@@ -17,6 +17,7 @@ import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.ui.main.MainActivity_; import com.stardust.scriptdroid.ui.main.MainActivity_;
import com.stardust.util.ClipboardUtil; import com.stardust.util.ClipboardUtil;
import com.stardust.util.MessageEvent; import com.stardust.util.MessageEvent;
import com.stardust.view.accessibility.AccessibilityService;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@@ -61,10 +62,14 @@ public class MainMenuNavigatorContent implements NavigatorContent {
Toast.makeText(mView.getContext(), R.string.text_layout_inspector_is_dumping, Toast.LENGTH_SHORT).show(); Toast.makeText(mView.getContext(), R.string.text_layout_inspector_is_dumping, Toast.LENGTH_SHORT).show();
return false; return false;
} }
if (inspector.getCapture() == null) { if (AccessibilityService.getInstance() == null) {
Toast.makeText(mView.getContext(), R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show(); Toast.makeText(mView.getContext(), R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show();
return false; return false;
} }
if (inspector.getCapture() == null) {
Toast.makeText(mView.getContext(), R.string.text_inspect_failed, Toast.LENGTH_SHORT).show();
return false;
}
return true; return true;
} }

View File

@@ -1,5 +1,7 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector; package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log; import android.util.Log;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
@@ -43,6 +45,17 @@ public class LayoutInspector {
} }
} }
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void refreshChildList(AccessibilityNodeInfo root) {
if (root == null)
return;
root.refresh();
int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
refreshChildList(root.getChild(i));
}
}
public boolean isDumping() { public boolean isDumping() {
return mDumping; return mDumping;
} }

View File

@@ -207,6 +207,7 @@
<string name="text_number_format_error">格式错误</string> <string name="text_number_format_error">格式错误</string>
<string name="text_accessibility_settings">打开无障碍服务</string> <string name="text_accessibility_settings">打开无障碍服务</string>
<string name="text_discard_record">放弃录制</string> <string name="text_discard_record">放弃录制</string>
<string name="text_inspect_failed">布局抓取失败,请关闭悬浮窗后动一下页面重试</string>
<string-array name="record_control_keys"> <string-array name="record_control_keys">
<item></item> <item></item>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged|typeAnnouncement|typeAssistReadingContext|typeContextClicked|typeGestureDetectionEnd|typeGestureDetectionStart|typeTouchExplorationGestureEnd|typeTouchExplorationGestureStart|typeTouchInteractionEnd|typeTouchInteractionStart|typeViewAccessibilityFocusCleared|typeViewAccessibilityFocused|typeViewClicked|typeViewHoverEnter|typeViewHoverExit|typeViewFocused|typeViewLongClicked|typeViewScrolled|typeViewSelected|typeViewTextChanged|typeViewTextSelectionChanged|typeViewTextTraversedAtMovementGranularity|typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged" android:accessibilityEventTypes="typeContextClicked|typeViewClicked|typeViewHoverEnter|typeViewHoverExit|typeViewFocused|typeViewLongClicked|typeViewScrolled|typeViewSelected|typeViewTextChanged|typeViewTextSelectionChanged|typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility" android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRequestEnhancedWebAccessibility"
android:canPerformGestures="true" android:canPerformGestures="true"
android:canRequestEnhancedWebAccessibility="true" android:canRequestEnhancedWebAccessibility="true"
android:canRetrieveWindowContent="true" android:canRetrieveWindowContent="true"

View File

@@ -1,22 +1,25 @@
package com.stardust.view.accessibility; package com.stardust.view.accessibility;
import android.content.Context; import android.content.Context;
import android.graphics.Rect;
import android.os.Build; import android.os.Build;
import android.support.annotation.CallSuper; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.InputDevice;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.TextView; import android.widget.FrameLayout;
import com.stardust.util.ScreenMetrics;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@@ -27,8 +30,6 @@ import java.util.concurrent.locks.ReentrantLock;
public class AccessibilityService extends android.accessibilityservice.AccessibilityService { public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
private AccessibilityNodeInfo mRootInActiveWindow;
private static final String TAG = "AccessibilityService"; private static final String TAG = "AccessibilityService";
@@ -38,6 +39,8 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
private static AccessibilityService instance; private static AccessibilityService instance;
private static boolean containsAllEventTypes = false; private static boolean containsAllEventTypes = false;
private static final Set<Integer> eventTypes = new HashSet<>(); private static final Set<Integer> eventTypes = new HashSet<>();
private volatile AccessibilityNodeInfo mRootInActiveWindow;
private Timer mTimer;
public static void addDelegate(int uniquePriority, AccessibilityDelegate delegate) { public static void addDelegate(int uniquePriority, AccessibilityDelegate delegate) {
mDelegates.put(uniquePriority, delegate); mDelegates.put(uniquePriority, delegate);
@@ -59,15 +62,6 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
@Override @Override
public void onAccessibilityEvent(final AccessibilityEvent event) { public void onAccessibilityEvent(final AccessibilityEvent event) {
Log.v(TAG, "onAccessibilityEvent: " + event); Log.v(TAG, "onAccessibilityEvent: " + event);
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|| event.getEventType() == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
|| event.getEventType() == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
AccessibilityNodeInfo root = super.getRootInActiveWindow();
if (root != null) {
mRootInActiveWindow = root;
Log.d(TAG, "rootInActiveWindow: " + mRootInActiveWindow);
}
}
if (!containsAllEventTypes && !eventTypes.contains(event.getEventType())) if (!containsAllEventTypes && !eventTypes.contains(event.getEventType()))
return; return;
for (Map.Entry<Integer, AccessibilityDelegate> entry : mDelegates.entrySet()) { for (Map.Entry<Integer, AccessibilityDelegate> entry : mDelegates.entrySet()) {
@@ -90,13 +84,17 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
@Override @Override
public AccessibilityNodeInfo getRootInActiveWindow() { public AccessibilityNodeInfo getRootInActiveWindow() {
return mRootInActiveWindow; try {
return super.getRootInActiveWindow();
} catch (IllegalStateException e) {
return null;
}
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
instance = null; instance = null;
mTimer.cancel();
super.onDestroy(); super.onDestroy();
} }
@@ -109,6 +107,16 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
LOCK.lock(); LOCK.lock();
ENABLED.signalAll(); ENABLED.signalAll();
LOCK.unlock(); LOCK.unlock();
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
AccessibilityNodeInfo root = getRootInActiveWindow();
if (root != null) {
mRootInActiveWindow = root;
}
}
}, 0, 100);
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行安卓的BUG??? // FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行安卓的BUG???
} }

View File

@@ -0,0 +1,27 @@
package com.stardust.view.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.view.accessibility.AccessibilityNodeInfo;
/**
* Created by Stardust on 2017/7/13.
*/
public class LayoutInspectService extends AccessibilityService {
private static LayoutInspectService instance;
public static LayoutInspectService getInstance() {
return instance;
}
@Override
protected void onServiceConnected() {
AccessibilityServiceInfo info = getServiceInfo();
info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(info);
super.onServiceConnected();
}
}