目录结构
- 在Android (AndroidManifest.xml) 中配置
<service
android:name="com.example.myapplication.TestAccessibilityService"
android:enabled="true"
android:exported="true"
android:label="抖音小助手"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
AndroidManifest.xml 整体配置文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.myapplication">
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
tools:ignore="ProtectedPermissions" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter >
<action android:name="com.ss.android.sdk.snssdk1128" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="snssdk1128" />
</intent-filter>
</activity>
<service
android:name="com.example.myapplication.TestAccessibilityService"
android:enabled="true"
android:exported="true"
android:label="抖音小助手"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
</application>
</manifest>
accessibility_service_config.xml 配置
android:packageNames 一定要配置抖音的包名 不然监听不了
<?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:packageNames="com.example.android.apis,com.tencent.mm,com.tencent.mobileqq,com.ss.android.ugc.aweme"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagDefault"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="2000"
android:canRetrieveWindowContent="true"
android:canPerformGestures="true"
android:canRequestFilterKeyEvents="true"
android:canRequestEnhancedWebAccessibility="true"
android:settingsActivity="com.example.myapplication.TestAccessibilityService"
/>
MainActivity.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.barrierFree);
Button st = findViewById(R.id.start);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!TestAccessibilityService.isStart()) {
Log.e("TAG", "onCreate:初始化" );
try {
startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
Log.e("TAG", "onCreate:初始化 try" );
} catch (Exception e) {
Log.e("TAG", "onCreate:初始化 catch" );
startActivity(new Intent(Settings.ACTION_SETTINGS));
e.printStackTrace();
}
}
}
});
st.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//抖音
boolean exist1 = checkAppInstalled(MainActivity.this, "com.ss.android.ugc.aweme");
//抖音极速版
//boolean exist1 = checkAppInstalled(getContext(), "com.ss.android.article.video");
//抖音火山版
//boolean exist1 = checkAppInstalled(getContext(), "com.ss.android.ugc.live");
if (exist1) {
Intent intent = new Intent();
//抖音 打开个人中心 104248958804 需要去获取抖音的UserId
// intent.setData(Uri.parse("snssdk1128://user/profile/104248958804"));
// 打开首页
intent.setData(Uri.parse("snssdk1128://feed?refer=web&gd_label=1"));
//抖音极速版
//intent.setData(Uri.parse("snssdk1112://user/profile/104248958804"));
//抖音火山版
//intent.setData(Uri.parse("snssdk1112://profile?id=104248958804"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
Toast.makeText(MainActivity.this, "请先安装此应用", Toast.LENGTH_SHORT).show();
}
}
});
}
private boolean checkAppInstalled(Context context, String pName) {
if (pName == null || pName.isEmpty()) {
return false;
}
final PackageManager packageManager = context.getPackageManager();
List<PackageInfo> info = packageManager.getInstalledPackages(0);
if (info == null || info.isEmpty()) {
return false;
}
for (int i = 0; i < info.size(); i++) {
if (pName.equals(info.get(i).packageName)) {
return true;
}
}
return false;
}
}
activity_main.xml
<?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"
tools:context=".MainActivity"
android:orientation="horizontal">
<Button
android:id="@+id/barrierFree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打开无障碍"/>
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始执行"/>
</LinearLayout>
TestAccessibilityService.java
package com.example.myapplication;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.RequiresApi;
import java.util.List;
public class TestAccessibilityService extends AccessibilityService {
private final String TAG = getClass().getName();
public static TestAccessibilityService mService;
public List<AccessibilityNodeInfo> list2 = null;
public List<AccessibilityNodeInfo> list3 = null;
public List<AccessibilityNodeInfo> list4 = null;
public List<AccessibilityNodeInfo> list5 = null;
public List<AccessibilityNodeInfo> list6 = null;
public List<AccessibilityNodeInfo> list7 = null;
public List<AccessibilityNodeInfo> list8 = null;
public List<AccessibilityNodeInfo> list9 = null;
public List<AccessibilityNodeInfo> list10 = null;
public List<AccessibilityNodeInfo> list11 = null;
public String st = "";
//初始化
@Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.e(TAG, "onServiceConnected:"+"O(∩_∩)O~~\r\n锁定中..." );
mService = this;
}
//实现辅助功能
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// System.out.println("Event Occurred");
AccessibilityNodeInfo rootNodeInfo = getRootInActiveWindow();
// Log.e(TAG, rootNodeInfo.toString());
int eventType = event.getEventType();
String packageName = event.getPackageName().toString();
String className = event.getClassName().toString();
//Log.d(Config.TAG,"packageName = " + packageName + ", className = " + className);
switch (eventType) {
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
//事件源:跳转到新的页面,或者弹出了window,dialog等
Log.e(TAG, "AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED跳转到新的页面");
if (className.equals("com.ss.android.ugc.aweme.main.MainActivity")){
// 关闭首页提示青年弹窗
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list8 = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.ss.android.ugc.aweme:id/a-5");
}
if (null != list8) {
for (AccessibilityNodeInfo info : list8) {
info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list2 = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.ss.android.ugc.aweme:id/hox");
}
if (null != list2) {
for (AccessibilityNodeInfo info : list2) {
Log.e(TAG, info.toString() );
info.getParent().getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
if (className.equals("com.lynx.tasm.behavior.KeyboardMonitor")){
//点击输入框
Log.e(TAG, "执行了输入框" );
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list3 = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.ss.android.ugc.aweme:id/et_search_kw");
}
if (null != list3) {
for (AccessibilityNodeInfo nodeInfo : list3) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Bundle arguments = new Bundle();
arguments.putCharSequence(
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, "111111");
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
}
}
}
}
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
Log.e(TAG, "AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED某个view的内容发生的变化");
case AccessibilityEvent.TYPE_VIEW_SCROLLED:
Log.e(TAG, "onServiceConnected:"+"实现辅助功能" );
Log.d("TAG","packageName = " + packageName + ", className = " + className);
if (className.equals("com.lynx.tasm.behavior.KeyboardMonitor")){
Log.e(TAG, "执行了搜索按钮" );
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list5 = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.ss.android.ugc.aweme:id/rzy");
}
if (null != list5) {
for (AccessibilityNodeInfo info : list5) {
clickByNode(this, info);
}
}
}
if (className.equals("androidx.recyclerview.widget.RecyclerView")){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list6 = rootNodeInfo.findAccessibilityNodeInfosByText("用户");
}
if (null != list6) {
for (AccessibilityNodeInfo info : list6) {
Log.e(TAG, info.toString());
clickByNode(this, info.getParent());
}
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list7 = rootNodeInfo.findAccessibilityNodeInfosByText("关注");
}
if (null != list7) {
for (AccessibilityNodeInfo info : list7) {
Log.e(TAG, info.toString());
}
}
}
//
//获取根节点
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
//匹配Text获取节点
List<AccessibilityNodeInfo> list1 = rootNode.findAccessibilityNodeInfosByText("match_text");
//匹配id获取节点
List<AccessibilityNodeInfo> list2 = rootNode.findAccessibilityNodeInfosByViewId("match_id");
//获取子节点
AccessibilityNodeInfo infoNode = rootNode.getChild(index);
}
}
/**
* 实现位置坐标点击
* @param service
* @param nodeInfo
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public static boolean clickByNode(AccessibilityService service, AccessibilityNodeInfo nodeInfo) {
if (service == null || nodeInfo == null) {
return false;
}
Rect rect = new Rect();
nodeInfo.getBoundsInScreen(rect);
int x = rect.centerX();
int y = rect.centerY();
Log.e("acc_", "要点击的像素点在手机屏幕位置::" + rect.centerX() + " " + rect.centerY());
Point point = new Point(x, y);
GestureDescription.Builder builder = new GestureDescription.Builder();
Path path = new Path();
path.moveTo(point.x, point.y);
builder.addStroke(new GestureDescription.StrokeDescription(path, 0L, 100L));
GestureDescription gesture = builder.build();
boolean isDispatched = service.dispatchGesture(gesture, new AccessibilityService.GestureResultCallback() {
@Override
public void onCompleted(GestureDescription gestureDescription) {
super.onCompleted(gestureDescription);
// LogUtil.d(TAG, "dispatchGesture onCompleted: 完成...");
}
@Override
public void onCancelled(GestureDescription gestureDescription) {
super.onCancelled(gestureDescription);
// LogUtil.d(TAG, "dispatchGesture onCancelled: 取消...");
}
}, null);
return isDispatched;
}
@Override
public void onInterrupt() {
Log.e(TAG, "onInterrupt: "+"(;′⌒`)\r\n功能被迫中断" );
mService = null;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy: "+"%>_<%\r\n功能已关闭" );
mService = null;
}
// 公共方法
/**
* 辅助功能是否启动
*/
public static boolean isStart() {
return mService != null;
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
class MyCallBack extends AccessibilityService.GestureResultCallback {
public MyCallBack() {
super();
}
@Override
public void onCompleted(GestureDescription gestureDescription) {
super.onCompleted(gestureDescription);
}
@Override
public void onCancelled(GestureDescription gestureDescription) {
super.onCancelled(gestureDescription);
}
}
抖音userid获取方式
1、首先打开手机上的抖音软件,点击右下角的“我"。
2、进入手机抖音我页面后,点击右上角的三横按钮。
3、弹出来的内容里,再点击“设置"。
4、双击抖音版本地方的空白处。
5丶多双击几次就会出现抖音uⅰd信息,点击uⅰd即可复制了。