前段时间,公司有个需求就是华为应用市场的下载量不高,问我能不能写个程序刷一下,
进入正题,Android里面有个辅助服务accessibilityservice ,这个服务可以监听到你想监听的一切,
写个myservice继承accessibilityservice ,
在AndroidManifest
<service android:name=".Myservice" android:label="辅助功能" 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/service_ass" /> </service>
这里是配置记得在res新建一个xml文件夹
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/accessibility_service_description" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:notificationTimeout="100" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:packageNames="com.huawei.appmarket,com.android.packageinstaller"
android:settingsActivity="com.example.hyt.monkey.android.accessibility.ServiceSettingsActivity" />
packageNames可以给多个,我这里就给了华为跟系统的
记得加上权限
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"></uses-permission> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"></uses-permission> <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.DELETE_PACKAGES" />
onAccessibilityEvent()这里是事件的回调。通过里面的AccessibilityEvent.TYPE_..可以取到各种状态,
但是跟我的需求没什么关系
getRootInActiveWindow()是拿到窗口所有的根节点,
可以通过findAccessibilityNodeInfosByText(“xx”)去查找想要的控件。
找到之后可以给它设置各种事件模拟。
也可以通过getRootInActiveWindow().getChild.getClassName拿到所有的控件属性,通过对比界面,去猜UI结构(很简单)。上面的种种记得要try起来因为有时候事件传回来了,但是找不到你想要查找的会报空。在catch里面用递归的形式去查找,
public class Myservice extends AccessibilityService { private boolean isCome =false; private boolean isComefocu=false; private boolean isComechind=false; private boolean isXiangqing=false; private boolean isanzhuang=false; private boolean isxiezai=false; private int text=nb; private Handler mHandler=new Handler(); @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onAccessibilityEvent(final AccessibilityEvent accessibilityEvent) { checkInstall(accessibilityEvent); if(text==0){//关闭应用 Killclass.kill("com.huawei.appmarket"); return; } if(accessibilityEvent.getPackageName().equals( "com.android.packageinstaller")&&isxiezai){ xiezaishiwu(); } if(accessibilityEvent.getPackageName().equals( "com.huawei.appmarket")&&isxiezai){ isCome =false; isComefocu=false; isComechind=false; isXiangqing=false; isanzhuang=false; isxiezai=false; Killclass.kill("com.huawei.appmarket"); // ActivityManager m= (ActivityManager) getSystemService(ACTIVITY_SERVICE); // m.killBackgroundProcesses("com.huawei.appmarket"); mHandler.postDelayed(new Runnable() { @Override public void run() {//启动应用 Intent intent =getPackageManager().getLaunchIntentForPackage("com.huawei.appmarket"); startActivity(intent); nb=--text; Toast.makeText(getApplication(),"还剩"+text+"次数",Toast.LENGTH_SHORT).show(); } },2000); } AccessibilityNodeInfo rootNode = getRootInActiveWindow(); Log.e("aaa", "onAccessibilityEvent: "+accessibilityEvent.getPackageName()); int eventType = accessibilityEvent.getEventType(); // Lo.e("aaa", "onAccessibilityEvent: "+eventType); //匹配Text获取节 if(!isCome){ homepage(); } if(isCome&&!isComechind){ getApp(); } if(isComechind&&!isXiangqing){ clickdown(); } if(isComechind&&isXiangqing&&isanzhuang){if(isAvilible(this,"com.xxx.xxx")){//包名 Log.e("aaa", "onAccessibilityEvent: "+isAvilible(this,"com.xxx.xxx")); unstallApp(); if(accessibilityEvent!=null&& accessibilityEvent.getPackageName().equals( "com.android.packageinstaller")&&isanzhuang&!isxiezai){//判断是否在packageinstaller上 AccessibilityNodeInfo rootNodexiezai = getRootInActiveWindow(); if(rootNodexiezai==null){ return; } mHandler.postDelayed(new Runnable() { @Override public void run() { download(accessibilityEvent); } },3000); /*for (int i = 0; i < rootNodexiezai.getChildCount(); i++) { for (int j = 0; j <rootNodexiezai.getChild(i).getChildCount() ; j++) { Log.e("aaa", "aaaaaaaa"+rootNodexiezai.getChild(i).getChild(j).getClassName()); if(rootNodexiezai.getChild(i).getChild(j).getClassName().equals("android.widget.Button")){ if(rootNodexiezai.getChild(i).getChildCount()==2){ rootNodexiezai.getChild(i).getChild(1).performAction(AccessibilityNodeInfo.ACTION_CLICK); isxiezai=true; } } } }*/ /* List<AccessibilityNodeInfo> download = rootNode.findAccessibilityNodeInfosByText("卸载"); List<AccessibilityNodeInfo> queren = rootNode.findAccessibilityNodeInfosByText("确定"); Log.e("aaa", "onAccessibilityEventxiezai: "+download.size()+queren.size()); if(download.size()>0&&queren.size()>0){ for (final AccessibilityNodeInfo n : queren) { n.performAction(AccessibilityNodeInfo.ACTION_CLICK); isxiezai=true; } }*/ } } } /* if(isComechind){ List<AccessibilityNodeInfo> jiumiaodai2 = rootNode.findAccessibilityNodeInfosByText("安装"); for (AccessibilityNodeInfo n : jiumiaodai2) { n.performAction(AccessibilityNodeInfo.ACTION_CLICK); isXiangqing=true; } }*/ switch (eventType) { case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: //收到通知栏消息 Log.e("aaa", "onAccessibilityEvent: "+"通知栏有消息了"); break; case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: //界面状态改变 Log.e("aaa", "onAccessibilityEvent: "+"界面状态改变了"); if(!isCome){ break; } if(!isComefocu){//一开始我是通过这里去做操作的,后来发现没必要,可以放到前面不需要判断状态,自己做好标记, ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("text", "应用name"); clipboard.setPrimaryClip(clip); lookupApp(); } /* for (AccessibilityNodeInfo n : rootNode) { if(n.isFocusable()){ Log.e("aaa", "onAccessibilityEvent: "+"这是可输入的"); } if(n.isEditable()){ Log.e("aaa", "onAccessibilityEvent: "+"我也不知道"); } }*/ //匹配id获取节点 // List<AccessibilityNodeInfo> list2 = rootNode.findAccessibilityNodeInfosByViewId("match_id"); //获取子节点 //AccessibilityNodeInfo infoNode = rootNode.getChild(0); //模拟点击事件 //模拟输入内容 break; case AccessibilityEvent.TYPE_VIEW_CLICKED: //点击事件 Log.e("aaa", "onAccessibilityEvent: "+"点击了"); break; case AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT: //文本改变 Log.e("aaa", "onAccessibilityEvent: "+"文本改变"); break; //省略其他的一堆可以监听的事件 } } private void uninstallApp() { AccessibilityNodeInfo rootNodeshibai = getRootInActiveWindow(); try{ List<AccessibilityNodeInfo> ok = rootNodeshibai.findAccessibilityNodeInfosByText("卸载失败"); List<AccessibilityNodeInfo> no = rootNodeshibai.findAccessibilityNodeInfosByText("确定"); if(ok.size()>0&&no.size()>0){ no.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK); } }catch (Exception e){ mHandler.postDelayed(new Runnable() { @Override public void run() { uninstallApp(); } },1500); } } private void lookupApp() { AccessibilityNodeInfo rootNode2 = getRootInActiveWindow(); try{ for (int i = 0; i < rootNode2.getChildCount(); i++) { // Log.e("aaa", "getChildCount: "+ rootNode2.getChild(i).getClassName()); for (int j = 0; j < rootNode2.getChild(i).getChildCount(); j++) { // Log.e("aaa", "getChildCount2: "+ rootNode2.getChild(i).getChild(j).getClassName());//模拟输入 if(rootNode2.getChild(i).getChild(j).getClassName().equals("android.widget.EditText")){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Log.e("aaa", "onAccessibilityEvent: "+"5.0"); Bundle arguments = new Bundle(); arguments.putCharSequence( AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, "应用name"); rootNode2.getChild(i).getChild(j).performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments); break; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { Log.e("aaa", "onAccessibilityEvent: "+"4.0"); // focus.performAction(AccessibilityNodeInfo.ACTION_CLICK); rootNode2.getChild(i).getChild(j).performAction(AccessibilityNodeInfo.ACTION_FOCUS); rootNode2.getChild(i).getChild(j).performAction(AccessibilityNodeInfo.ACTION_PASTE); isComefocu=true; break; } } } } }catch (Exception e){ lookupApp(); } } private void getApp() { AccessibilityNodeInfo rootNode = getRootInActiveWindow(); try{ List<AccessibilityNodeInfo> jiumiaodai = rootNode.findAccessibilityNodeInfosByText("应用name"); //Log.e("aaa", "onAccessibilityEventjiumiaodai: "+jiumiaodai.size()); if(!isComechind&&jiumiaodai.size()>0){ AccessibilityNodeInfo rootNodean = getRootInActiveWindow(); // List<AccessibilityNodeInfo> jiumiaodai2= rootNodean.findAccessibilityNodeInfosByText("安装"); // Log.e("aaa", "onAccessibilityEventjiumiaodai2: "+rootNodean.getChildCount()); for (int i = 0; i <rootNodean.getChildCount() ; i++) { // Log.e("aaa", "onAccessibilityEventan: "+rootNodean.getChild(i).getClassName()); if("android.widget.ListView".equals(rootNodean.getChild(i).getClassName())){ for (int j = 0; j < rootNodean.getChild(i).getChildCount(); j++) { rootNodean.getChild(i).getChild(j).performAction(AccessibilityNodeInfo.ACTION_CLICK); //Log.e("aaa", "onAccessibilityEventan: "+rootNodean.getChild(i).getChild(j).getClassName()); isComechind=true; break; } } } /* for (AccessibilityNodeInfo n : jiumiaodai2) { Log.e("aaa", "onAccessibilityEvent: "+isComechind); n.performAction(AccessibilityNodeInfo.ACTION_CLICK); isComechind=true; // break; }*/ } }catch (Exception e){ getApp(); } } private void homepage() { try { isCome=true; AccessibilityNodeInfo rootNode = getRootInActiveWindow(); // List<AccessibilityNodeInfo> list=null;//这里是华为首页输入view,但是它是不可输入的只能点击,我直接遍历所有的控件,去套的,
华为版本不同控件位置也不同。这里比较早的版本。你可以自己去套进去或者把华为市场反编译查看xml.
rootNode.getChild(0).getChild(1).performAction(AccessibilityNodeInfo.ACTION_CLICK); /* list = rootNode.findAccessibilityNodeInfosByText("晚上请你吃鸡"); if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("进入二次元的世界"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("10个宝宝"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("下班别走"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("与书为伴"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("他们为何如此成功"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("让美好"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("别人家的孩子"); } if(list.size()==0){ list = rootNode.findAccessibilityNodeInfosByText("精彩直播随时看"); } for (final AccessibilityNodeInfo n : list) { isCome=true; mHandler.postDelayed(new Runnable() { @Override public void run() { n.performAction(AccessibilityNodeInfo.ACTION_CLICK); } },2000); break; }*/ }catch (Exception e){ mHandler.postDelayed(new Runnable() { @Override public void run() { homepage(); } },2000); } } private void clickdown() {//详情里面点击下载,同样你进入详情页面先把控件遍历出来对比找到不需要的下载控件。 AccessibilityNodeInfo rootNodejmd = getRootInActiveWindow(); try { for (int i = 0; i < rootNodejmd.getChildCount(); i++) { if("android.widget.LinearLayout".equals(rootNodejmd.getChild(i).getClassName())){ for (int j = 0; j <rootNodejmd.getChild(i).getChildCount() ; j++) { if("android.view.View".equals(rootNodejmd.getChild(i).getChild(j).getClassName())){ rootNodejmd.getChild(i).getChild(j).performAction(AccessibilityNodeInfo.ACTION_CLICK); isXiangqing=true; } } } } }catch (Exception e){ mHandler.postDelayed(new Runnable() { @Override public void run() { clickdown(); } },1000); } } private void download(final AccessibilityEvent accessibilityEvent) {//方法名字什么的不重要~~,哈哈, AccessibilityNodeInfo rootNodexiezai = getRootInActiveWindow(); try { /*for (int i = 0; i < rootNodexiezai.getChildCount(); i++) { for (int j = 0; j <rootNodexiezai.getChild(i).getChildCount() ; j++) { Log.e("aaa", "aaaaaaaa"+rootNodexiezai.getChild(i).getChild(j).getClassName()); if(rootNodexiezai.getChild(i).getChild(j).getClassName().equals("android.widget.Button")){ if(rootNodexiezai.getChild(i).getChildCount()==2){ rootNodexiezai.getChild(i).getChild(1).performAction(AccessibilityNodeInfo.ACTION_CLICK); isxiezai=true; } } } }*/ List<AccessibilityNodeInfo> xiezai = rootNodexiezai.findAccessibilityNodeInfosByText("卸载"); List<AccessibilityNodeInfo> queren = rootNodexiezai.findAccessibilityNodeInfosByText("确定"); Log.e("aaa", "onAccessibilityEventxiezai: "+xiezai.size()+queren.size()); if(xiezai.size()>0&&queren.size()>0){ for (final AccessibilityNodeInfo n : queren) { n.performAction(AccessibilityNodeInfo.ACTION_CLICK); isxiezai=true; } } /* List<AccessibilityNodeInfo> download = accessibilityEvent.getSource().findAccessibilityNodeInfosByText("卸载"); List<AccessibilityNodeInfo> queding = accessibilityEvent.getSource().findAccessibilityNodeInfosByText("确定"); if(download.size()>0&&queding.size()>0){ queding.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK); isxiezai=true; }*/ }catch (Exception e){ mHandler.postDelayed(new Runnable() { @Override public void run() { download(accessibilityEvent); } },2000); } } private void checkInstall(AccessibilityEvent event) { // source不为空 boolean notNull = event.getSource() != null; if (notNull) { // 当前界面为安装界面 boolean installPage = event.getPackageName().equals( "com.android.packageinstaller"); if (installPage) { // 当前标题为应用标题 boolean thisApk = checkTitle(event.getSource(), "应用name"); if (thisApk) { doInstall(event); } } } } private boolean checkTitle(AccessibilityNodeInfo source, String title) { List<AccessibilityNodeInfo> titleList = source .findAccessibilityNodeInfosByText(title); for (AccessibilityNodeInfo node : titleList) { Log.d("test", node.toString()); if (node.getClassName().equals("android.widget.TextView")) { return true; } } return false; } private boolean isAvilible( Context context, String packageName ) { final PackageManager packageManager = context.getPackageManager(); List<PackageInfo> pinfo = packageManager.getInstalledPackages(0); List<String> pName = new ArrayList<String>(); if (pinfo != null) { for (int i = 0; i < pinfo.size(); i++) { String pn = pinfo.get(i).packageName; pName.add(pn); } } return pName.contains(packageName); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public void unstallApp(){ /* PackageManager packageManager = getPackageManager(); PackageInstaller packageInstaller = packageManager.getPackageInstaller(); packageInstaller.uninstall("com.jinqianbao.jmd",null);*/ Intent uninstall_intent = new Intent(); uninstall_intent.setAction(Intent.ACTION_DELETE); uninstall_intent.setData(Uri.parse("package:"+"com.xxxx.xxx")); uninstall_intent.setFlags(FLAG_ACTIVITY_NEW_TASK); startActivity(uninstall_intent); } private void doInstall(AccessibilityEvent event) { List<AccessibilityNodeInfo> next_nodes = event.getSource() .findAccessibilityNodeInfosByText("下一步"); if (next_nodes != null && !next_nodes.isEmpty()) { AccessibilityNodeInfo node; for (int i = 0; i < next_nodes.size(); i++) { node = next_nodes.get(i); if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK); getInstall(); } } } /* List<AccessibilityNodeInfo> ok_nodes = event.getSource() .findAccessibilityNodeInfosByText("打开"); if (ok_nodes != null && !ok_nodes.isEmpty()) { AccessibilityNodeInfo node; for (int i = 0; i < ok_nodes.size(); i++) { node = ok_nodes.get(i); if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } }*/ } private void getInstall() { AccessibilityNodeInfo rootNode = getRootInActiveWindow(); List<AccessibilityNodeInfo> unintall_nodes = rootNode.findAccessibilityNodeInfosByText("安装"); if (unintall_nodes != null && !unintall_nodes.isEmpty()) { AccessibilityNodeInfo node; for (int i = 0; i < unintall_nodes.size(); i++) { Log.e("aaa", "doInstall: "+unintall_nodes.get(i).getClassName()); node = unintall_nodes.get(i); if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK); isanzhuang=true; } } if(!isanzhuang){ getInstall(); } } }同理这样可以去监听淘宝网去限制你的女朋友~,我有个大胆的想法。。。(玩笑)