【10】AccessibilityService實現探探app的自動化喜歡和不喜歡+ [as 3.0如何開啟層級呼叫uiautomatorviewer]
目前版本3.1.8 僅供學習使用!!!!!切勿用作非法用途,否則後果自負!
直接寫這個東西 可能是有些唐突
因為你們可能不知道這是一個什麼玩意 如果你想看過於這個Accessibility服務的一些資料
可以到 我的分類 下面去看
下面將直接進入正題
AccessibilityService 的出現原本為了幫助盲人 來那啥那啥和那啥的
沒想到卻被我們那啥那啥和那啥了
他使用方法需要手動到無障礙裡面去開啟 開啟成功以後程式碼就開始運行了
整合的一般步驟就是
建立服務 繼承AccessibilityService實現相關方法
package com.example.liuan.test; import android.accessibilityservice.AccessibilityService; import android.annotation.SuppressLint; import android.app.Service; import android.content.Intent; import android.graphics.Rect; import android.os.Environment; import android.os.IBinder; import android.util.Log; import android.view.KeyEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Toast; import java.io.DataOutputStream; import java.io.File; import java.io.OutputStream; import java.util.Arrays; import java.util.List; import java.util.Random; public class MyService extends AccessibilityService { private static final String TAG = "MyService"; // 大多數的手機包名一樣,聯想部分機型的手機不一樣 private String[] packageNames = {"com.p1.mobile.putong"}; int startFlag = 0; AccessibilityNodeInfo[] noteInfo = new AccessibilityNodeInfo[2]; @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getSource() != null) { findNodesByText(event, "繼續探索"); } switch (event.getEventType()) { case AccessibilityEvent.TYPE_VIEW_CLICKED: if (SpUtils.getBoolean(this, "reSet", false)) { SpUtils.putBoolean(this, "reSet", false); startFlag = 0; } if (startFlag == 0) { //記錄正確 startFlag = 1; noteInfo[0] = event.getSource(); } else if (startFlag == 1) { //記錄錯誤 只記錄一次即可 startFlag = 2; noteInfo[1] = event.getSource(); } if (startFlag == 2) { autoClick(); } break; } } private void autoClick() { try { String time = SpUtils.getString(this, "time", "1000"); Thread.sleep(Integer.parseInt(time)); } catch (InterruptedException e) { e.printStackTrace(); } String time = SpUtils.getString(this, "like", "50"); int percent = Integer.parseInt(time); //隨機數字 是1-100 int random = new Random().nextInt(100) + 1; //如果設定了百分之50 那麼就是各一半 //如果設定了百分之10 那麼就是點第一個 8 10 Log.e(TAG, "onAccessibilityEvent:random " + random); Log.e(TAG, "onAccessibilityEvent:percent " + percent); if (random <= percent) { //第一次按鍵 noteInfo[0].performAction(AccessibilityNodeInfo.ACTION_CLICK); } else { noteInfo[1].performAction(AccessibilityNodeInfo.ACTION_CLICK); } } @Override public void onInterrupt() { startFlag = 0; } @Override public void onDestroy() { super.onDestroy(); startFlag = 0; } private void findNodesByText(AccessibilityEvent event, String text) { List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(text); if (nodes != null && !nodes.isEmpty()) { for (AccessibilityNodeInfo info : nodes) { if (info.isClickable()) {// 只有根據節點資訊是下一步,安裝,完成,開啟,且是可以點選的時候,才執行後面的點選操作 if ("繼續探索".equals(text)) { info.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } } } } private boolean isTextExist(AccessibilityEvent event, String text) { List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(text); if (nodes != null && !nodes.isEmpty()) { for (AccessibilityNodeInfo info : nodes) { if (info.isClickable()) {// 只有根據節點資訊是下一步,安裝,完成,開啟,且是可以點選的時候,才執行後面的點選操作 if ("繼續探索".equals(text)) { return true; } } } } return false; } }
我的思路 我簡單來說一下 因為就算你層級用的沒問題 但是卻獲取不到id
我就急中生智 使用了event.getSource() 把這個儲存到陣列 讓自己點兩下 然後開始模仿我的點選
這個方法不僅僅使用與這裡 可以用作好多的地方
AccessiblityServices 要比指令碼穩定 指令碼存在一種情況就是指令碼會崩潰 或者由於某個地方的偏移導致點選錯誤
這個從節點點選 徹底的解決了這個問題 無論開發者怎麼騷操作 這裡都可以點選 好氣的
獲取那個檔案的id 或者文字什麼的 用到了studio工具中的(本文程式碼風騷 沒有用到這個)
G:\android\sdk\tools\bin\uiautomatorviewer.bat
as 3.0居然喪盡天良把他搞沒了 反正我沒找到 可能是沒了
只能去sdk 目錄下去找了 如果你記憶力夠好的話找到你曾經安裝的sdk目錄
如果記憶力不夠好 可以在alt+ctrl+s System Settings-->Android SDK看到你的sdk目錄 找到開啟即可
具體使用方法這裡不做教程
四大元件逃不過的清單檔案
application節點下
<service android:name=".MyService" android:enabled="true" android:exported="true" 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/accessibility" /> </service>
res/xml/accessibility.xml 沒有這個目錄請自行建立
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/des"
android:notificationTimeout="100"
android:packageNames="com.p1.mobile.putong" />
<resources>
<string name="app_name">Test</string>
<string name="des">僅供學習使用,切勿亂搞,否則後果自負</string>
</resources>
MainActivity
package com.example.liuan.test;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button mBtOpen;
private EditText mEtDelay;
private EditText mEtLike;
/**
* 儲存配置
*/
private Button mBtReset;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// String apkRoot="chmod 777 "+getPackageCodePath();
//
// SystemManager.RootCommand(apkRoot);
initView();
initData();
}
private void initData() {
SpUtils.putString(this, "time", mEtDelay.getText().toString().trim());
SpUtils.putString(this, "like", mEtLike.getText().toString().trim());
SpUtils.putBoolean(MainActivity.this, "reSet", true);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Toast.makeText(MainActivity.this, "半徑", Toast.LENGTH_LONG);
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
Toast.makeText(MainActivity.this, "半徑", Toast.LENGTH_LONG);
mBtOpen.setText("已經關閉");
return true;
}
return super.onKeyDown(keyCode, event);
}
private void initView() {
mBtOpen = (Button) findViewById(R.id.bt_open);
mBtOpen.setOnClickListener(this);
mEtDelay = (EditText) findViewById(R.id.et_delay);
mEtLike = (EditText) findViewById(R.id.et_like);
mEtLike.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
initData();
}
});
mEtDelay.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
initData();
}
});
mBtReset = (Button) findViewById(R.id.bt_reset);
mBtReset.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.bt_open:
initData();
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);
break;
case R.id.bt_reset:
initData();
break;
}
}
}
SpUtils
package com.example.liuan.test;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Created by liuan on 2018-04-28.
*/
public class SpUtils {
private static SharedPreferences sp;
public static void getSharedPreference(Context context){
if(sp==null){
sp=context.getSharedPreferences("config",context.MODE_PRIVATE);
}
}
public static void putString(Context context,String key,String value){
getSharedPreference(context);
sp.edit().putString(key,value).commit();
}
public static String getString(Context context,String key,String defValue){
getSharedPreference(context);
return sp.getString(key,defValue);
}
public static boolean getBoolean(Context context,String key,boolean defValue){
getSharedPreference(context);
return sp.getBoolean(key,false);
}
public static void putBoolean(Context context,String key,boolean value){
getSharedPreference(context);
sp.edit().putBoolean(key,value).commit();
}
}
佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/bt_open"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="開啟/關閉服務" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/bt_reset"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="儲存配置" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<TextView
android:layout_width="60sp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="延時:s"
android:textColor="@android:color/holo_red_dark" />
<EditText
android:id="@+id/et_delay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="number"
android:text="6000" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<TextView
android:layout_width="60sp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="喜歡:x/%"
android:textColor="@android:color/holo_red_dark" />
<EditText
android:id="@+id/et_like"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="number"
android:text="94" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:text="本軟體僅供學習使用~!!!!\n開啟服務 點選一個喜歡 再點選一個不喜歡 就開始了,如果點選喜歡 出現了繼續探索,要進主頁點重新設定 再點選 喜歡 和不喜歡~"
android:textColor="@android:color/holo_red_dark"
android:textSize="22sp" />
</LinearLayout>
開始方法 並不是直接點開啟就開啟了
第一步 開啟探探點選的服務
第二步 開啟探探先把其他的第一次引導的東西點完 然後 點一個喜歡 點一個不喜歡 再然後就能看到神奇的自動了
那天我本來想寫了按音量鍵暫停的方法 後來發現沒必要 暫停服務就行了