├── app
├── .gitignore
├── release
│ ├── app-release.apk
│ └── output.json
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── back.png
│ │ │ │ ├── logo.png
│ │ │ │ ├── start.png
│ │ │ │ ├── stop.png
│ │ │ │ ├── setting.png
│ │ │ │ ├── user_set.png
│ │ │ │ ├── activated.png
│ │ │ │ └── not_active.png
│ │ │ ├── xml
│ │ │ │ └── accessibility_service_config.xml
│ │ │ ├── values
│ │ │ │ ├── styles.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── colors.xml
│ │ │ ├── layout
│ │ │ │ ├── float_static.xml
│ │ │ │ ├── activity_user_setting.xml
│ │ │ │ └── activity_main.xml
│ │ │ └── drawable-xxhdpi
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── nice
│ │ │ │ ├── service
│ │ │ │ ├── MyService.java
│ │ │ │ └── TikTokAccessibilityService.java
│ │ │ │ ├── tiktoktool
│ │ │ │ ├── FloatingManager.java
│ │ │ │ ├── NativeDataManager.java
│ │ │ │ ├── FloatingView.java
│ │ │ │ ├── UserSettingActivity.java
│ │ │ │ └── MainActivity.java
│ │ │ │ ├── utils
│ │ │ │ ├── ApplicationUtil.java
│ │ │ │ ├── JumpPermissionManagement.java
│ │ │ │ ├── PerformClickUtils.java
│ │ │ │ └── AESUtils.java
│ │ │ │ ├── entity
│ │ │ │ ├── ActivationCode.java
│ │ │ │ └── ViewId.java
│ │ │ │ └── config
│ │ │ │ └── Config.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── nice
│ │ │ └── tiktoktool
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── nice
│ │ └── tiktoktool
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── .idea
├── misc.xml
├── gradle.xml
└── assetWizardSettings.xml
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/release/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/release/app-release.apk
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/back.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/logo.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/start.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/stop.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/setting.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/user_set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/user_set.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/activated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/activated.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/not_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys58/TikTokTool/HEAD/app/src/main/res/mipmap-xxhdpi/not_active.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches/build_file_checksums.ser
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | .DS_Store
9 | /build
10 | /captures
11 | .externalNativeBuild
12 |
--------------------------------------------------------------------------------
/app/release/output.json:
--------------------------------------------------------------------------------
1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Nov 24 15:58:26 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/accessibility_service_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/nice/tiktoktool/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/float_static.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/nice/tiktoktool/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.nice.tiktoktool", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 | #-dontwarn okio.**
23 | #-keep class okio.** { *; }
24 | #-dontwarn com.alibaba.**
25 | #-keep com.alibaba.** { *; }
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/service/MyService.java:
--------------------------------------------------------------------------------
1 | package com.nice.service;
2 |
3 | import android.app.Service;
4 | import android.content.Intent;
5 | import android.os.IBinder;
6 |
7 | import com.nice.tiktoktool.FloatingView;
8 |
9 | public class MyService extends Service {
10 | public static final String ACTION = "action";
11 | public static final String SHOW = "show";
12 | public static final String HIDE = "hide";
13 | private FloatingView mFloatingView;
14 |
15 | @Override
16 | public void onCreate() {
17 | super.onCreate();
18 | mFloatingView = new FloatingView(this);
19 | }
20 |
21 | @Override
22 | public IBinder onBind(Intent intent) {
23 | return null;
24 | }
25 |
26 | @Override
27 | public int onStartCommand(Intent intent, int flags, int startId) {
28 | if (intent != null) {
29 | String action = intent.getStringExtra(ACTION);
30 | if (SHOW.equals(action)) {
31 | mFloatingView.show();
32 | } else if (HIDE.equals(action)) {
33 | mFloatingView.hide();
34 | }
35 | }
36 | return super.onStartCommand(intent, flags, startId);
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 日天小坦克
3 | 抖音引流脚本
4 | 开始执行
5 | 打开悬浮窗权限
6 | 打开服务
7 | 服务状态:
8 | 悬浮窗权限状态:
9 | 打开抖音
10 | 关注
11 | 私信
12 | 选择功能:
13 | 私信内容(多条话术用|分开,程序会随机发送):
14 | 取消/关注速度:
15 | 用户设置
16 | 私信速度:
17 | 激活码:
18 | 激活
19 | 返回
20 | 唯一官方群:489611929
21 | 取消关注
22 | 检查更新
23 | http://tt.update.yl888.site
24 | 抖音版本
25 |
26 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | defaultConfig {
6 | applicationId "com.nice.tiktoktool"
7 | minSdkVersion 18
8 | targetSdkVersion 26
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(include: ['*.jar'], dir: 'libs')
23 | implementation 'com.android.support:appcompat-v7:26.1.0'
24 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
25 | testImplementation 'junit:junit:4.12'
26 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
28 | implementation 'com.squareup.okhttp3:okhttp:3.6.0'
29 | implementation 'com.squareup.okio:okio:1.11.0'
30 | implementation 'com.alibaba:fastjson:1.2.53'
31 | implementation 'com.android.support:design:26.1.0'
32 | implementation 'com.android.support:cardview-v7:26.0.0-alpha1'
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/tiktoktool/FloatingManager.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.view.WindowManager;
6 |
7 | /**
8 | * 悬浮窗管理类
9 | */
10 | public class FloatingManager {
11 |
12 | private WindowManager mWindowManager;
13 | private static FloatingManager mInstance;
14 | private Context mContext;
15 |
16 | public static FloatingManager getInstance(Context context) {
17 | if (mInstance == null) {
18 | mInstance = new FloatingManager(context);
19 | }
20 | return mInstance;
21 | }
22 |
23 | private FloatingManager(Context context) {
24 | mContext = context;
25 | mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);//获得WindowManager对象
26 | }
27 |
28 | /**
29 | * 添加悬浮窗
30 | *
31 | * @param view
32 | * @param params
33 | * @return
34 | */
35 | protected boolean addView(View view, WindowManager.LayoutParams params) {
36 | try {
37 | mWindowManager.addView(view, params);
38 | return true;
39 | } catch (Exception e) {
40 | }
41 | return false;
42 | }
43 |
44 | /**
45 | * 移除悬浮窗
46 | *
47 | * @param view
48 | * @return
49 | */
50 | protected boolean removeView(View view) {
51 | try {
52 | mWindowManager.removeView(view);
53 | return true;
54 | } catch (Exception e) {
55 | }
56 | return false;
57 | }
58 |
59 | /**
60 | * 更新悬浮窗参数
61 | *
62 | * @param view
63 | * @param params
64 | * @return
65 | */
66 | protected boolean updateView(View view, WindowManager.LayoutParams params) {
67 | try {
68 | mWindowManager.updateViewLayout(view, params);
69 | return true;
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 | return false;
74 | }
75 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/tiktoktool/NativeDataManager.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 |
7 | public class NativeDataManager {
8 |
9 | private SharedPreferences mPreference;
10 |
11 | public NativeDataManager(Context context) {
12 | mPreference = context.getSharedPreferences("setting", Context.MODE_PRIVATE);
13 | }
14 |
15 | public Long getAttentionSpeed() {
16 | return mPreference.getLong("attentionSpeed", 8000);
17 | }
18 |
19 | public void setAttentionSpeed(Long speed) {
20 | mPreference.edit().putLong("attentionSpeed", speed).apply();
21 | }
22 |
23 | public Long getPrivatelySpeed() {
24 | return mPreference.getLong("privatelySpeed", 8000);
25 | }
26 |
27 | public void setPrivatelySpeed(Long privatelySpeed) {
28 | mPreference.edit().putLong("privatelySpeed", privatelySpeed).apply();
29 | }
30 |
31 | public String getPrivatelyContent() {
32 | return mPreference.getString("privatelyContent", "测试");
33 | }
34 |
35 | public void setPrivatelyContent(String privatelyContent) {
36 | mPreference.edit().putString("privatelyContent", privatelyContent).apply();
37 | }
38 |
39 | public String getActivationCode() {
40 | return mPreference.getString("activationCode", "");
41 | }
42 |
43 | public void setActivationCode(String activationCode) {
44 | mPreference.edit().putString("activationCode", activationCode).apply();
45 | }
46 |
47 | public String getEndTime() {
48 | return mPreference.getString("endTime", "");
49 | }
50 |
51 | public void setEndTime(String activationCode) {
52 | mPreference.edit().putString("endTime", activationCode).apply();
53 | }
54 |
55 | public String getTikTokVersion() {
56 | return mPreference.getString("tikTokVersion", "3.4.0");
57 | }
58 |
59 | public void setTikTokVersion(String tikTokVersion) {
60 | mPreference.edit().putString("tikTokVersion", tikTokVersion).apply();
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/utils/ApplicationUtil.java:
--------------------------------------------------------------------------------
1 | package com.nice.utils;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager;
6 |
7 | import java.io.File;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.io.RandomAccessFile;
11 | import java.util.UUID;
12 |
13 | public class ApplicationUtil {
14 |
15 | private static String sID = null;
16 | private static final String INSTALLATION = "INSTALLATION";
17 |
18 | public synchronized static String id(Context context) {
19 | if (sID == null) {
20 | File installation = new File(context.getFilesDir(), INSTALLATION);
21 | try {
22 | if (!installation.exists())
23 | writeInstallationFile(installation);
24 | sID = readInstallationFile(installation);
25 | } catch (Exception e) {
26 | throw new RuntimeException(e);
27 | }
28 | }
29 | return sID;
30 | }
31 |
32 | private static String readInstallationFile(File installation) throws IOException {
33 | RandomAccessFile f = new RandomAccessFile(installation, "r");
34 | byte[] bytes = new byte[(int) f.length()];
35 | f.readFully(bytes);
36 | f.close();
37 | return new String(bytes);
38 | }
39 |
40 | private static void writeInstallationFile(File installation) throws IOException {
41 | FileOutputStream out = new FileOutputStream(installation);
42 | String id = UUID.randomUUID().toString();
43 | out.write(id.getBytes());
44 | out.close();
45 | }
46 |
47 | public static String getVersionName(Context context) {
48 | PackageManager manager = context.getPackageManager();
49 | PackageInfo info = null;
50 | try {
51 | info = manager.getPackageInfo(context.getPackageName(), 0);
52 | } catch (PackageManager.NameNotFoundException e) {
53 | e.printStackTrace();
54 | }
55 | return info.versionName;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/entity/ActivationCode.java:
--------------------------------------------------------------------------------
1 | package com.nice.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | * This class was generated by MyBatis Generator.
8 | * This class corresponds to the database table activation_code
9 | *
10 | * @mbg.generated do_not_delete_during_merge
11 | */
12 | public class ActivationCode implements Serializable {
13 | private Long id;
14 |
15 | private String activationCode;
16 |
17 | private Integer state;
18 |
19 | private Date startTime;
20 |
21 | private Date endTime;
22 |
23 | private String installationCode;
24 |
25 | private String deviceInfo;
26 |
27 | private Integer type;
28 |
29 | private Integer sold;
30 |
31 | private Date soldTime;
32 |
33 | private static final long serialVersionUID = 1L;
34 |
35 | public Long getId() {
36 | return id;
37 | }
38 |
39 | public void setId(Long id) {
40 | this.id = id;
41 | }
42 |
43 | public String getActivationCode() {
44 | return activationCode;
45 | }
46 |
47 | public void setActivationCode(String activationCode) {
48 | this.activationCode = activationCode;
49 | }
50 |
51 | public Integer getState() {
52 | return state;
53 | }
54 |
55 | public void setState(Integer state) {
56 | this.state = state;
57 | }
58 |
59 | public Date getStartTime() {
60 | return startTime;
61 | }
62 |
63 | public void setStartTime(Date startTime) {
64 | this.startTime = startTime;
65 | }
66 |
67 | public Date getEndTime() {
68 | return endTime;
69 | }
70 |
71 | public void setEndTime(Date endTime) {
72 | this.endTime = endTime;
73 | }
74 |
75 | public String getInstallationCode() {
76 | return installationCode;
77 | }
78 |
79 | public void setInstallationCode(String installationCode) {
80 | this.installationCode = installationCode;
81 | }
82 |
83 | public String getDeviceInfo() {
84 | return deviceInfo;
85 | }
86 |
87 | public void setDeviceInfo(String deviceInfo) {
88 | this.deviceInfo = deviceInfo;
89 | }
90 |
91 | public Integer getType() {
92 | return type;
93 | }
94 |
95 | public void setType(Integer type) {
96 | this.type = type;
97 | }
98 |
99 | public Integer getSold() {
100 | return sold;
101 | }
102 |
103 | public void setSold(Integer sold) {
104 | this.sold = sold;
105 | }
106 |
107 | public Date getSoldTime() {
108 | return soldTime;
109 | }
110 |
111 | public void setSoldTime(Date soldTime) {
112 | this.soldTime = soldTime;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/.idea/assetWizardSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_user_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
20 |
21 |
29 |
30 |
38 |
39 |
40 |
41 |
46 |
47 |
50 |
51 |
57 |
58 |
59 |
60 |
67 |
68 |
69 |
74 |
75 |
80 |
81 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
103 |
104 |
105 |
111 |
112 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/config/Config.java:
--------------------------------------------------------------------------------
1 | package com.nice.config;
2 |
3 | import android.content.Context;
4 |
5 | import android.os.Build;
6 |
7 | import com.nice.entity.ViewId;
8 | import com.nice.tiktoktool.NativeDataManager;
9 |
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | public class Config {
14 |
15 | // public static final String CODE_VALIDATE_URL = "http://192.168.10.135:8088/auth/codeValidate";
16 | public static final String CODE_VALIDATE_URL = "http://tt.yl888.site:8088/auth/codeValidate";
17 |
18 | public static final Integer CONCERN = 1;
19 | public static final Integer PRIVATELY = 2;
20 | public static final Integer CANCEL_CONCERN = 3;
21 | public static final Integer COMMENT_PRIVATELY = 4;
22 |
23 | public static final String ATTENTION_BTN = "ATTENTION_BTN";
24 | public static final String USER_LIST_BG = "USER_LIST_BG";
25 | public static final String USER_HP_MORE = "USER_HP_MORE";
26 | public static final String MORE_TALK_BTN = "MORE_TALK_BTN";
27 | public static final String SEND_MSG_ET = "SEND_MSG_ET";
28 | public static final String SEND_MSG_BTN = "SEND_MSG_BTN";
29 | public static final String TALK_BACK = "TALK_BACK";
30 | public static final String MORE_BACK = "MORE_BACK";
31 | public static final String USER_HP_BACK = "USER_HP_BACK";
32 | public static final String LIST_USER_NAME = "LIST_USER_NAME";
33 |
34 |
35 | public static final String DEVICE_INFO = Build.MANUFACTURER + "-" + Build.DEVICE + "-" + Build.VERSION.SDK_INT;
36 |
37 | private Boolean status;
38 | private Integer option;
39 | private Boolean activated;
40 |
41 | private Map viewIdByVersionMap;
42 | private List viewIds;
43 |
44 | private static NativeDataManager mNativeDataManager;
45 |
46 | private static Config instance = new Config();
47 |
48 | private Config() {
49 |
50 | }
51 |
52 | public static synchronized Config getInstance(Context context) {
53 | if (instance == null) {
54 | instance = new Config();
55 | }
56 | if (mNativeDataManager == null) {
57 | mNativeDataManager = new NativeDataManager(context);
58 | }
59 | return instance;
60 | }
61 |
62 | public List getViewIds() {
63 | return viewIds;
64 | }
65 |
66 | public void setViewIds(List viewIds) {
67 | this.viewIds = viewIds;
68 | }
69 |
70 | public Long getAttentionSpeed() {
71 | return mNativeDataManager.getAttentionSpeed();
72 | }
73 |
74 | public void setAttentionSpeed(Long attentionSpeed) {
75 | mNativeDataManager.setAttentionSpeed(attentionSpeed * 1000);
76 | }
77 |
78 | public Long getPrivatelySpeed() {
79 | return mNativeDataManager.getPrivatelySpeed();
80 | }
81 |
82 | public void setPrivatelySpeed(Long privatelySpeed) {
83 | mNativeDataManager.setPrivatelySpeed(privatelySpeed * 1000);
84 | }
85 |
86 | public boolean getStatus() {
87 | return (status == null) ? false : status;
88 | }
89 |
90 | public void setStatus(boolean status) {
91 | this.status = status;
92 | }
93 |
94 | public Integer getOption() {
95 | return option == null ? CONCERN : option;
96 | }
97 |
98 | public void setOption(Integer option) {
99 | this.option = option;
100 | }
101 |
102 | public String[] getPrivatelyContent() {
103 | return mNativeDataManager.getPrivatelyContent().split("\\|");
104 | }
105 |
106 | public String getPrivatelyContentText() {
107 | return mNativeDataManager.getPrivatelyContent();
108 | }
109 |
110 | public void setPrivatelyContent(String privatelyContent) {
111 | mNativeDataManager.setPrivatelyContent(privatelyContent);
112 | }
113 |
114 | public String getActivationCode() {
115 | return mNativeDataManager.getActivationCode();
116 | }
117 |
118 | public void setActivationCode(String activationCode) {
119 | mNativeDataManager.setActivationCode(activationCode);
120 | }
121 |
122 | public Boolean getActivated() {
123 | return activated != null && activated;
124 | }
125 |
126 | public void setActivated(Boolean activated) {
127 | this.activated = activated;
128 | }
129 |
130 | public String getEndTime() {
131 | return mNativeDataManager.getEndTime();
132 | }
133 |
134 | public void setEndTime(String activationCode) {
135 | mNativeDataManager.setEndTime(activationCode);
136 | }
137 |
138 | public Map getViewIdByVersionMap() {
139 | return viewIdByVersionMap;
140 | }
141 |
142 | public void setViewIdByVersionMap(Map viewIdByVersionMap) {
143 | this.viewIdByVersionMap = viewIdByVersionMap;
144 | }
145 |
146 | public String getTikTokVersion() {
147 | return mNativeDataManager.getTikTokVersion();
148 | }
149 |
150 | public void setTikTokVersion(String tikTokVersion) {
151 | mNativeDataManager.setTikTokVersion(tikTokVersion);
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/entity/ViewId.java:
--------------------------------------------------------------------------------
1 | package com.nice.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | *
8 | * This class was generated by MyBatis Generator.
9 | * This class corresponds to the database table tt_view_id
10 | *
11 | * @mbg.generated do_not_delete_during_merge
12 | */
13 | public class ViewId implements Serializable {
14 | /**
15 | *
16 | * This field was generated by MyBatis Generator.
17 | * This field corresponds to the database column tt_view_id.id
18 | *
19 | * @mbg.generated
20 | */
21 | private Integer id;
22 |
23 | /**
24 | *
25 | * This field was generated by MyBatis Generator.
26 | * This field corresponds to the database column tt_view_id.click_info
27 | *
28 | * @mbg.generated
29 | */
30 | private String clickInfo;
31 |
32 | /**
33 | *
34 | * This field was generated by MyBatis Generator.
35 | * This field corresponds to the database column tt_view_id.view_id
36 | *
37 | * @mbg.generated
38 | */
39 | private String viewId;
40 |
41 | /**
42 | *
43 | * This field was generated by MyBatis Generator.
44 | * This field corresponds to the database column tt_view_id.version
45 | *
46 | * @mbg.generated
47 | */
48 | private String version;
49 |
50 | /**
51 | *
52 | * This field was generated by MyBatis Generator.
53 | * This field corresponds to the database column tt_view_id.time
54 | *
55 | * @mbg.generated
56 | */
57 | private Date time;
58 |
59 | /**
60 | * This field was generated by MyBatis Generator.
61 | * This field corresponds to the database table tt_view_id
62 | *
63 | * @mbg.generated
64 | */
65 | private static final long serialVersionUID = 1L;
66 |
67 | /**
68 | * This method was generated by MyBatis Generator.
69 | * This method returns the value of the database column tt_view_id.id
70 | *
71 | * @return the value of tt_view_id.id
72 | *
73 | * @mbg.generated
74 | */
75 | public Integer getId() {
76 | return id;
77 | }
78 |
79 | /**
80 | * This method was generated by MyBatis Generator.
81 | * This method sets the value of the database column tt_view_id.id
82 | *
83 | * @param id the value for tt_view_id.id
84 | *
85 | * @mbg.generated
86 | */
87 | public void setId(Integer id) {
88 | this.id = id;
89 | }
90 |
91 | /**
92 | * This method was generated by MyBatis Generator.
93 | * This method returns the value of the database column tt_view_id.click_info
94 | *
95 | * @return the value of tt_view_id.click_info
96 | *
97 | * @mbg.generated
98 | */
99 | public String getClickInfo() {
100 | return clickInfo;
101 | }
102 |
103 | /**
104 | * This method was generated by MyBatis Generator.
105 | * This method sets the value of the database column tt_view_id.click_info
106 | *
107 | * @param clickInfo the value for tt_view_id.click_info
108 | *
109 | * @mbg.generated
110 | */
111 | public void setClickInfo(String clickInfo) {
112 | this.clickInfo = clickInfo;
113 | }
114 |
115 | /**
116 | * This method was generated by MyBatis Generator.
117 | * This method returns the value of the database column tt_view_id.view_id
118 | *
119 | * @return the value of tt_view_id.view_id
120 | *
121 | * @mbg.generated
122 | */
123 | public String getViewId() {
124 | return viewId;
125 | }
126 |
127 | /**
128 | * This method was generated by MyBatis Generator.
129 | * This method sets the value of the database column tt_view_id.view_id
130 | *
131 | * @param viewId the value for tt_view_id.view_id
132 | *
133 | * @mbg.generated
134 | */
135 | public void setViewId(String viewId) {
136 | this.viewId = viewId;
137 | }
138 |
139 | /**
140 | * This method was generated by MyBatis Generator.
141 | * This method returns the value of the database column tt_view_id.version
142 | *
143 | * @return the value of tt_view_id.version
144 | *
145 | * @mbg.generated
146 | */
147 | public String getVersion() {
148 | return version;
149 | }
150 |
151 | /**
152 | * This method was generated by MyBatis Generator.
153 | * This method sets the value of the database column tt_view_id.version
154 | *
155 | * @param version the value for tt_view_id.version
156 | *
157 | * @mbg.generated
158 | */
159 | public void setVersion(String version) {
160 | this.version = version;
161 | }
162 |
163 | /**
164 | * This method was generated by MyBatis Generator.
165 | * This method returns the value of the database column tt_view_id.time
166 | *
167 | * @return the value of tt_view_id.time
168 | *
169 | * @mbg.generated
170 | */
171 | public Date getTime() {
172 | return time;
173 | }
174 |
175 | /**
176 | * This method was generated by MyBatis Generator.
177 | * This method sets the value of the database column tt_view_id.time
178 | *
179 | * @param time the value for tt_view_id.time
180 | *
181 | * @mbg.generated
182 | */
183 | public void setTime(Date time) {
184 | this.time = time;
185 | }
186 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/utils/JumpPermissionManagement.java:
--------------------------------------------------------------------------------
1 | package com.nice.utils;
2 |
3 | /**
4 | * 跳转设置页面
5 | */
6 |
7 | import android.app.Activity;
8 | import android.content.ComponentName;
9 | import android.content.Intent;
10 | import android.net.Uri;
11 | import android.os.Build;
12 | import android.provider.Settings;
13 | import android.support.v7.appcompat.BuildConfig;
14 | import android.util.Log;
15 |
16 | import java.io.BufferedReader;
17 | import java.io.IOException;
18 | import java.io.InputStreamReader;
19 |
20 | public class JumpPermissionManagement {
21 | /**
22 | * Build.MANUFACTURER
23 | */
24 | private static final String MANUFACTURER_HUAWEI = "Huawei";//华为
25 | private static final String MANUFACTURER_MEIZU = "Meizu";//魅族
26 | private static final String MANUFACTURER_XIAOMI = "Xiaomi";//小米
27 | private static final String MANUFACTURER_SONY = "Sony";//索尼
28 | private static final String MANUFACTURER_OPPO = "OPPO";
29 | private static final String MANUFACTURER_LG = "LG";
30 | private static final String MANUFACTURER_VIVO = "vivo";
31 | private static final String MANUFACTURER_SAMSUNG = "samsung";//三星
32 | private static final String MANUFACTURER_LETV = "Letv";//乐视
33 | private static final String MANUFACTURER_ZTE = "ZTE";//中兴
34 | private static final String MANUFACTURER_YULONG = "YuLong";//酷派
35 | private static final String MANUFACTURER_LENOVO = "LENOVO";//联想
36 |
37 |
38 | public static boolean gotoPermissionSetting(Activity activity) {
39 | Intent intent = new Intent();
40 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
41 | String packageName = BuildConfig.APPLICATION_ID;
42 |
43 | boolean other = false;
44 |
45 | switch (Build.MANUFACTURER) {
46 | case MANUFACTURER_HUAWEI: // 华为
47 | intent.putExtra("packageName", packageName);
48 | intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"));
49 | break;
50 | case MANUFACTURER_MEIZU: // 魅族
51 | intent.setAction("com.meizu.safe.security.SHOW_APPSEC");
52 | intent.addCategory(Intent.CATEGORY_DEFAULT);
53 | intent.putExtra("packageName", packageName);
54 | break;
55 | case MANUFACTURER_XIAOMI: // 小米
56 | String rom = getMiuiVersion();
57 | if ("V6".equals(rom) || "V7".equals(rom)) {
58 | intent.setAction("miui.intent.action.APP_PERM_EDITOR");
59 | intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
60 | intent.putExtra("extra_pkgname", packageName);
61 | } else if ("V8".equals(rom) || "V9".equals(rom)) {
62 | intent.setAction("miui.intent.action.APP_PERM_EDITOR");
63 | intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
64 | intent.putExtra("extra_pkgname", packageName);
65 | } else {
66 | SystemConfig(activity);
67 | }
68 | break;
69 | case MANUFACTURER_SONY: // 索尼
70 | intent.putExtra("packageName", packageName);
71 | intent.setComponent(new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity"));
72 | break;
73 | case MANUFACTURER_OPPO: // OPPO
74 | intent.putExtra("packageName", packageName);
75 | intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity"));
76 | break;
77 | case MANUFACTURER_LETV: // 乐视
78 | intent.putExtra("packageName", packageName);
79 | intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps"));
80 | break;
81 | case MANUFACTURER_LG: // LG
82 | intent.setAction("android.intent.action.MAIN");
83 | intent.putExtra("packageName", packageName);
84 | ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");
85 | intent.setComponent(comp);
86 | break;
87 | case MANUFACTURER_SAMSUNG: // 三星
88 | default:
89 | other = false;
90 | break;
91 | }
92 | activity.startActivity(intent);
93 | return other;
94 | }
95 |
96 | /**
97 | * 系统设置界面
98 | *
99 | * @param activity
100 | */
101 | public static void SystemConfig(Activity activity) {
102 | Intent intent = new Intent(Settings.ACTION_SETTINGS);
103 | activity.startActivity(intent);
104 | }
105 |
106 | private static String getMiuiVersion() {
107 | String propName = "ro.miui.ui.version.name";
108 | String line;
109 | BufferedReader input;
110 | try {
111 | Process p = Runtime.getRuntime().exec("getprop " + propName);
112 | input = new BufferedReader(
113 | new InputStreamReader(p.getInputStream()), 1024);
114 | line = input.readLine();
115 | input.close();
116 | } catch (IOException ex) {
117 | ex.printStackTrace();
118 | return null;
119 | }
120 | Log.i("", "MiuiVersion = " + line);
121 | return line;
122 | }
123 |
124 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/tiktoktool/FloatingView.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import android.content.Context;
4 | import android.graphics.PixelFormat;
5 | import android.os.Build;
6 | import android.view.Gravity;
7 | import android.view.LayoutInflater;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.WindowManager;
11 | import android.widget.FrameLayout;
12 | import android.widget.ImageView;
13 | import android.widget.Toast;
14 |
15 | import com.nice.config.Config;
16 | import com.nice.service.TikTokAccessibilityService;
17 |
18 | /**
19 | * 悬浮窗view
20 | */
21 | public class FloatingView extends FrameLayout {
22 | private Context mContext;
23 | private View mView;
24 | private ImageView beginBtn;
25 | private WindowManager.LayoutParams mParams;
26 | private FloatingManager mWindowManager;
27 |
28 |
29 | private final int statusHeight;
30 | int sW;
31 | private float mTouchStartX;
32 | private float mTouchStartY;
33 | private float x;
34 | private float y;
35 | private float mLastX;
36 | private float mLastY;
37 | private float mStartX;
38 | private float mStartY;
39 | private long mLastTime;
40 | private long mCurrentTime;
41 |
42 | public FloatingView(Context context) {
43 | super(context);
44 | mContext = context.getApplicationContext();
45 | LayoutInflater mLayoutInflater = LayoutInflater.from(context);
46 | mView = mLayoutInflater.inflate(R.layout.float_static, null);
47 | beginBtn = mView.findViewById(R.id.begin_btn);
48 | mWindowManager = FloatingManager.getInstance(mContext);
49 | statusHeight = getStatusHeight(context);
50 |
51 | beginBtn.setOnTouchListener(new View.OnTouchListener() {
52 |
53 | @Override
54 | public boolean onTouch(View v, MotionEvent event) {
55 | //获取相对屏幕的坐标,即以屏幕左上角为原点
56 | x = event.getRawX();
57 | y = event.getRawY();
58 | switch (event.getAction()) {
59 | case MotionEvent.ACTION_DOWN: //捕获手指触摸按下动作
60 | //获取相对View的坐标,即以此View左上角为原点
61 | mTouchStartX = event.getX();
62 | mTouchStartY = event.getY();
63 | mStartX = event.getRawX();
64 | mStartY = event.getRawY();
65 | mLastTime = System.currentTimeMillis();
66 | break;
67 |
68 |
69 | case MotionEvent.ACTION_MOVE: //捕获手指触摸移动动作
70 | updateViewPosition();
71 | break;
72 |
73 |
74 | case MotionEvent.ACTION_UP: //捕获手指触摸离开动作
75 | mLastX = event.getRawX();
76 | mLastY = event.getRawY();
77 |
78 | mCurrentTime = System.currentTimeMillis();
79 | if (mCurrentTime - mLastTime < 1500) {
80 | if (Math.abs(mStartX - mLastX) < 10.0 && Math.abs(mStartY - mLastY) < 10.0) {
81 | //处理点击的事件
82 | click();
83 | }
84 | }
85 | break;
86 | }
87 | return true;
88 | }
89 | });
90 | }
91 |
92 | private void updateViewPosition() {
93 | WindowManager wm = (WindowManager) getContext()
94 | .getSystemService(Context.WINDOW_SERVICE);
95 | int width = wm.getDefaultDisplay().getWidth();
96 | int height = wm.getDefaultDisplay().getHeight();
97 | //更新浮动窗口位置参数
98 | mParams.x = width - (int) x - (int) mTouchStartX;
99 | mParams.y = (int) y - (height / 2);
100 | mWindowManager.updateView(mView, mParams); //刷新显示
101 | }
102 |
103 | public void click() {
104 | if (Config.getInstance(getContext()).getActivated()) {
105 | if (Config.getInstance(getContext()).getStatus()) {
106 | Config.getInstance(getContext()).setStatus(false);
107 | beginBtn.setImageResource(R.mipmap.start);
108 | TikTokAccessibilityService.executing = false;
109 | Toast.makeText(getContext(), "停止执行...", Toast.LENGTH_SHORT).show();
110 | TikTokAccessibilityService.privateLetterList.clear();
111 | TikTokAccessibilityService.attentionCount = 0;
112 | } else {
113 | Config.getInstance(getContext()).setStatus(true);
114 | beginBtn.setImageResource(R.mipmap.stop);
115 | Toast.makeText(getContext(), "开始执行...", Toast.LENGTH_SHORT).show();
116 | }
117 | } else {
118 | Toast.makeText(getContext(), "软件未激活!", Toast.LENGTH_LONG).show();
119 | }
120 | }
121 |
122 | public void show() {
123 | mParams = new WindowManager.LayoutParams();
124 | mParams.gravity = Gravity.CENTER | Gravity.RIGHT;
125 | mParams.x = 0;
126 | mParams.y = 0;
127 | //总是出现在应用程序窗口之上
128 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0
129 | mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
130 | } else {
131 | mParams.type = WindowManager.LayoutParams.TYPE_PHONE;
132 | }
133 | mParams.format = PixelFormat.TRANSLUCENT;
134 | mParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams
135 | .FLAG_NOT_FOCUSABLE;
136 | mParams.format = PixelFormat.TRANSPARENT;
137 | mParams.width = LayoutParams.WRAP_CONTENT;
138 | mParams.height = LayoutParams.WRAP_CONTENT;
139 | mWindowManager.addView(mView, mParams);
140 | }
141 |
142 | public void hide() {
143 | mWindowManager.removeView(mView);
144 | }
145 |
146 | /**
147 | * 获得状态栏的高度
148 | *
149 | * @param context
150 | * @return
151 | */
152 | public static int getStatusHeight(Context context) {
153 |
154 |
155 | int statusHeight = -1;
156 | try {
157 | Class clazz = Class.forName("com.android.internal.R$dimen");
158 | Object object = clazz.newInstance();
159 | int height = Integer.parseInt(clazz.getField("status_bar_height")
160 | .get(object).toString());
161 | statusHeight = context.getResources().getDimensionPixelSize(height);
162 | } catch (Exception e) {
163 | e.printStackTrace();
164 | }
165 | return statusHeight;
166 | }
167 |
168 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/utils/PerformClickUtils.java:
--------------------------------------------------------------------------------
1 | package com.nice.utils;
2 |
3 | import android.accessibilityservice.AccessibilityService;
4 | import android.accessibilityservice.AccessibilityServiceInfo;
5 | import android.content.Context;
6 | import android.os.Build;
7 | import android.util.Log;
8 | import android.view.accessibility.AccessibilityManager;
9 | import android.view.accessibility.AccessibilityNodeInfo;
10 |
11 | import com.nice.config.Config;
12 |
13 | import java.util.List;
14 |
15 | public class PerformClickUtils {
16 |
17 |
18 | /**
19 | * 在当前页面查找文字内容并点击
20 | *
21 | * @param text
22 | */
23 | public static void findTextAndClick(AccessibilityService accessibilityService, String text) {
24 |
25 | AccessibilityNodeInfo accessibilityNodeInfo = accessibilityService.getRootInActiveWindow();
26 | if (accessibilityNodeInfo == null) {
27 | return;
28 | }
29 |
30 | List nodeInfoList = accessibilityNodeInfo.findAccessibilityNodeInfosByText(text);
31 | if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
32 | for (AccessibilityNodeInfo nodeInfo : nodeInfoList) {
33 | if (nodeInfo != null && (text.equals(nodeInfo.getText()) || text.equals(nodeInfo.getContentDescription()))) {
34 | performClick(nodeInfo);
35 | break;
36 | }
37 | }
38 | }
39 | }
40 |
41 |
42 | /**
43 | * 检查viewId进行点击
44 | *
45 | * @param accessibilityService
46 | * @param id
47 | */
48 | public static void findViewIdAndClick(AccessibilityService accessibilityService, String id) {
49 |
50 | AccessibilityNodeInfo accessibilityNodeInfo = accessibilityService.getRootInActiveWindow();
51 | if (accessibilityNodeInfo == null) {
52 | return;
53 | }
54 |
55 | List nodeInfoList = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);
56 | if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
57 | for (AccessibilityNodeInfo nodeInfo : nodeInfoList) {
58 | if (nodeInfo != null) {
59 | performClick(nodeInfo);
60 | break;
61 | }
62 | }
63 | }
64 | }
65 |
66 | /**
67 | * 检查viewId进行滑动
68 | *
69 | * @param accessibilityService
70 | * @param id
71 | */
72 | public static boolean findViewIdAndScroll(AccessibilityService accessibilityService, String id) {
73 |
74 | AccessibilityNodeInfo accessibilityNodeInfo = accessibilityService.getRootInActiveWindow();
75 | if (accessibilityNodeInfo == null) {
76 | return false;
77 | }
78 |
79 | List nodeInfoList = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);
80 | if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
81 | for (AccessibilityNodeInfo nodeInfo : nodeInfoList) {
82 | if (nodeInfo != null) {
83 | return performScroll(nodeInfo);
84 | }
85 | }
86 | }
87 | return false;
88 | }
89 |
90 |
91 | /**
92 | * 在当前页面查找对话框文字内容并点击
93 | *
94 | * @param text1 默认点击text1
95 | * @param text2
96 | */
97 | public static void findDialogAndClick(AccessibilityService accessibilityService, String text1, String text2) {
98 |
99 | AccessibilityNodeInfo accessibilityNodeInfo = accessibilityService.getRootInActiveWindow();
100 | if (accessibilityNodeInfo == null) {
101 | return;
102 | }
103 |
104 | List dialogWait = accessibilityNodeInfo.findAccessibilityNodeInfosByText(text1);
105 | List dialogConfirm = accessibilityNodeInfo.findAccessibilityNodeInfosByText(text2);
106 | if (!dialogWait.isEmpty() && !dialogConfirm.isEmpty()) {
107 | for (AccessibilityNodeInfo nodeInfo : dialogWait) {
108 | if (nodeInfo != null && text1.equals(nodeInfo.getText())) {
109 | performClick(nodeInfo);
110 | break;
111 | }
112 | }
113 | }
114 |
115 | }
116 |
117 | //模拟点击事件
118 | public static void performClick(AccessibilityNodeInfo nodeInfo) {
119 | if (nodeInfo == null) {
120 | return;
121 | }
122 | if (nodeInfo.isClickable()) {
123 | nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
124 | } else {
125 | performClick(nodeInfo.getParent());
126 | }
127 | }
128 |
129 | //模拟滑动事件
130 | public static boolean performScroll(AccessibilityNodeInfo nodeInfo) {
131 | if (nodeInfo == null) {
132 | return false;
133 | }
134 | if (nodeInfo.isScrollable()) {
135 | return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
136 | } else {
137 | performClick(nodeInfo.getParent());
138 | }
139 | return false;
140 | }
141 |
142 | //模拟返回事件
143 | public static void performBack(AccessibilityService service) {
144 | if (service == null) {
145 | return;
146 | }
147 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
148 | try {
149 | Thread.sleep(200);
150 | } catch (InterruptedException e) {
151 | e.printStackTrace();
152 | }
153 | service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
154 | }
155 | }
156 |
157 | /**
158 | * 跳转指定标记页面
159 | */
160 | public static void JumpViewByViewId(AccessibilityService accessibilityService, String fromId, String toId, long pauseTime) throws InterruptedException {
161 | do {
162 | PerformClickUtils.findViewIdAndClick(accessibilityService, fromId);
163 | Thread.sleep(pauseTime);
164 | }
165 | while (accessibilityService.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(toId).isEmpty() && Config.getInstance(accessibilityService).getStatus());
166 | }
167 |
168 | /**
169 | * 跳转指定标记页面
170 | */
171 | public static void JumpViewByViewInfo(AccessibilityService accessibilityService, AccessibilityNodeInfo info, String toId, long pauseTime) throws InterruptedException {
172 | do {
173 | PerformClickUtils.performClick(info);
174 | Thread.sleep(pauseTime);
175 | }
176 | while (accessibilityService.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(toId).isEmpty() && Config.getInstance(accessibilityService).getStatus());
177 | }
178 |
179 | /**
180 | * 跳转指定标记页面
181 | */
182 | public static void JumpViewByViewText(AccessibilityService accessibilityService, String text, String toId, long pauseTime) throws InterruptedException {
183 | do {
184 | PerformClickUtils.findTextAndClick(accessibilityService, text);
185 | Thread.sleep(pauseTime);
186 | }
187 | while (accessibilityService.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(toId).isEmpty() && Config.getInstance(accessibilityService).getStatus());
188 | }
189 |
190 | /**
191 | * 判断AccessibilityService服务是否已经启动
192 | *
193 | * @param context
194 | * @return
195 | */
196 | public static boolean isStartAccessibilityService(Context context) {
197 | AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
198 | List serviceInfos = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
199 | for (AccessibilityServiceInfo info : serviceInfos) {
200 | String id = info.getId();
201 | if (id.contains("TikTokAccessibilityService")) {
202 | return true;
203 | }
204 | }
205 | return false;
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/tiktoktool/UserSettingActivity.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.os.Message;
9 | import android.support.design.widget.TextInputEditText;
10 | import android.view.View;
11 | import android.widget.*;
12 |
13 | import com.alibaba.fastjson.JSONArray;
14 | import com.alibaba.fastjson.JSONObject;
15 | import com.nice.config.Config;
16 | import com.nice.entity.ActivationCode;
17 | import com.nice.entity.ViewId;
18 | import com.nice.utils.AESUtils;
19 | import com.nice.utils.ApplicationUtil;
20 |
21 | import java.io.IOException;
22 | import java.text.SimpleDateFormat;
23 | import java.util.HashMap;
24 | import java.util.List;
25 | import java.util.Map;
26 |
27 | import okhttp3.Call;
28 | import okhttp3.Callback;
29 | import okhttp3.MediaType;
30 | import okhttp3.OkHttpClient;
31 | import okhttp3.Request;
32 | import okhttp3.RequestBody;
33 | import okhttp3.Response;
34 |
35 | public class UserSettingActivity extends Activity {
36 |
37 | private TextInputEditText activationCodeEt;
38 | private Button activation_btn;
39 | private ProgressBar progressBar;
40 | private TextView endTimeTv, checkUpdatetv;
41 | private ImageView settingBackBtn;
42 |
43 | /*构造一个Handler,主要作用有:1)供非UI线程发送Message 2)处理Message并完成UI更新*/
44 | public Handler uiHandler = new Handler(new Handler.Callback() {
45 | @Override
46 | public boolean handleMessage(Message msg) {
47 | switch (msg.what) {
48 | case 200:
49 | progressBar.setVisibility(View.GONE);
50 | Bundle bundle = msg.getData();
51 | JSONObject data = JSONObject.parseObject(bundle.getString("data"));
52 | if (data.getInteger("code") == 0) {
53 | if (data.getInteger("valid") == 1) {
54 | ActivationCode activationCode = JSONObject.toJavaObject(data.getJSONObject("data"), ActivationCode.class);
55 |
56 | //获得viewId信息
57 | List list = JSONArray.parseArray(data.getString("viewIds"), ViewId.class);
58 | Map viewIdMap = new HashMap<>();
59 | for (ViewId viewId : list) {
60 | viewIdMap.put(viewId.getClickInfo(), viewId.getViewId());
61 | }
62 | //配置
63 | Config.getInstance(getApplicationContext()).setViewIdByVersionMap(viewIdMap);
64 |
65 | Config.getInstance(getApplicationContext()).setActivationCode(activationCode.getActivationCode());
66 | Config.getInstance(getApplicationContext()).setActivated(true);
67 | Config.getInstance(getApplicationContext()).setEndTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(activationCode.getEndTime()));
68 | Toast.makeText(getApplicationContext(), "激活成功!", Toast.LENGTH_LONG).show();
69 | activationCodeEt.setText(Config.getInstance(getApplicationContext()).getActivationCode());
70 | endTimeTv.setText(Config.getInstance(getApplicationContext()).getEndTime());
71 | finish();
72 | } else {
73 | Config.getInstance(getApplicationContext()).setEndTime(" - ");
74 | Config.getInstance(getApplicationContext()).setActivated(false);
75 | activationCodeEt.setError(data.getString("msg"));
76 | }
77 | } else {
78 | Config.getInstance(getApplicationContext()).setEndTime(" - ");
79 | Config.getInstance(getApplicationContext()).setActivated(false);
80 | activationCodeEt.setError(data.getString("msg"));
81 | }
82 | break;
83 | case 500:
84 | progressBar.setVisibility(View.GONE);
85 | Config.getInstance(getApplicationContext()).setEndTime(" - ");
86 | Config.getInstance(getApplicationContext()).setActivated(false);
87 | Toast.makeText(getApplicationContext(), "连接服务器失败!", Toast.LENGTH_LONG).show();
88 | break;
89 | default:
90 | break;
91 |
92 | }
93 | return false;
94 | }
95 | });
96 |
97 | @Override
98 | protected void onCreate(Bundle savedInstanceState) {
99 | super.onCreate(savedInstanceState);
100 | setContentView(R.layout.activity_user_setting);
101 |
102 | activationCodeEt = findViewById(R.id.activation_code_et);
103 | activation_btn = findViewById(R.id.activation_btn);
104 | progressBar = findViewById(R.id.setting_progress_bar);
105 | endTimeTv = findViewById(R.id.end_time_tv);
106 | settingBackBtn = findViewById(R.id.setting_back_btn);
107 | checkUpdatetv = findViewById(R.id.check_update_tv);
108 |
109 | activation_btn.setOnClickListener(new View.OnClickListener() {
110 | @Override
111 | public void onClick(View view) {
112 | requestDeviceInfo();
113 | }
114 | });
115 | settingBackBtn.setOnClickListener(new View.OnClickListener() {
116 | @Override
117 | public void onClick(View view) {
118 | finish();
119 | }
120 | });
121 |
122 | checkUpdatetv.setOnClickListener(new View.OnClickListener() {
123 | @Override
124 | public void onClick(View v) {
125 | Toast.makeText(getApplicationContext(), "当前版本:" + ApplicationUtil.getVersionName(getApplicationContext()), Toast.LENGTH_SHORT).show();
126 | Uri uri = Uri.parse(getString(R.string.update_path));
127 | Intent intent = new Intent(Intent.ACTION_VIEW, uri);
128 | startActivity(intent);
129 | }
130 | });
131 |
132 | activationCodeEt.setText(Config.getInstance(this).getActivationCode());
133 | endTimeTv.setText(Config.getInstance(this).getEndTime());
134 | }
135 |
136 | public void requestDeviceInfo() {
137 |
138 | progressBar.setVisibility(View.VISIBLE);
139 |
140 | MediaType mediaType = MediaType.parse("application/json; charset=utf-8");//"类型,字节码"
141 |
142 | JSONObject encryptedDataEntity = new JSONObject();
143 | JSONObject jsonObject = new JSONObject();
144 | jsonObject.put("activationCode", activationCodeEt.getText());
145 | jsonObject.put("InstallationCode", ApplicationUtil.id(this));
146 | jsonObject.put("deviceInfo", Config.DEVICE_INFO);
147 | encryptedDataEntity.put("data", AESUtils.encode(jsonObject.toString()));
148 | //json字符串
149 | String value = String.valueOf(encryptedDataEntity);
150 | //1.创建OkHttpClient对象
151 | OkHttpClient okHttpClient = new OkHttpClient();
152 | //2.通过RequestBody.create 创建requestBody对象
153 | RequestBody requestBody = RequestBody.create(mediaType, value);
154 | //3.创建Request对象,设置URL地址,将RequestBody作为post方法的参数传入
155 | Request request = new Request.Builder().url(Config.CODE_VALIDATE_URL).post(requestBody).build();
156 | //4.创建一个call对象,参数就是Request请求对象
157 | Call call = okHttpClient.newCall(request);
158 | //5.请求加入调度,重写回调方法
159 | call.enqueue(new Callback() {
160 |
161 | @Override
162 | public void onFailure(Call call, IOException e) {
163 | e.printStackTrace();
164 | new Thread() {
165 | public void run() {
166 | uiHandler.sendEmptyMessage(500);
167 | }
168 | }.start();
169 | }
170 |
171 | @Override
172 | public void onResponse(Call call, final Response response) throws IOException {
173 | final JSONObject encryptedData = JSONObject.parseObject(response.body().string());
174 | new Thread() {
175 | public void run() {
176 | Bundle bundle = new Bundle();
177 | bundle.putString("data", AESUtils.decode(encryptedData.getString("data")));
178 | Message message = new Message();
179 | message.what = 200;
180 | message.setData(bundle);
181 | uiHandler.sendMessage(message);
182 | }
183 | }.start();
184 | }
185 | });
186 | }
187 |
188 | @Override
189 | protected void onResume() {
190 | super.onResume();
191 | }
192 |
193 | @Override
194 | protected void onPause() {
195 | super.onPause();
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #f48fb1
4 | #ec407a
5 | #e91e63
6 | #ffffff
7 | #fffff0
8 | #ffffe0
9 | #ffff00
10 | #fffafa
11 | #fffaf0
12 | #fffacd
13 | #fff8dc
14 | #fff5ee
15 | #fff0f5
16 | #ffefd5
17 | #ffebcd
18 | #ffe4e1
19 | #ffe4c4
20 | #ffe4b5
21 | #ffdead
22 | #ffdab9
23 | #ffd700
24 | #ffc0cb
25 | #ffb6c1
26 | #ffa500
27 | #ffa07a
28 | #ff8c00
29 | #ff7f50
30 | #ff69b4
31 | #ff6347
32 | #ff4500
33 | #ff1493
34 | #ff00ff
35 | #ff00ff
36 | #ff0000
37 | #fdf5e6
38 | #fafad2
39 | #faf0e6
40 | #faebd7
41 | #fa8072
42 | #f8f8ff
43 | #f5fffa
44 | #f5f5f5
45 | #f5f5dc
46 | #f5deb3
47 | #f4a460
48 | #f0ffff
49 | #f0fff0
50 | #f0f8ff
51 | #f0e68c
52 | #f08080
53 | #eee8aa
54 | #ee82ee
55 | #e9967a
56 | #e6e6fa
57 | #e0ffff
58 | #deb887
59 | #dda0dd
60 | #dcdcdc
61 | #dc143c
62 | #db7093
63 | #daa520
64 | #da70d6
65 | #d8bfd8
66 | #d3d3d3
67 | #d3d3d3
68 | #d2b48c
69 | #d2691e
70 | #cd853f
71 | #cd5c5c
72 | #c71585
73 | #c0c0c0
74 | #bdb76b
75 | #bc8f8f
76 | #ba55d3
77 | #b8860b
78 | #b22222
79 | #b0e0e6
80 | #b0c4de
81 | #afeeee
82 | #adff2f
83 | #add8e6
84 | #a9a9a9
85 | #a9a9a9
86 | #a52a2a
87 | #a0522d
88 | #9932cc
89 | #98fb98
90 | #9400d3
91 | #9370db
92 | #90ee90
93 | #8fbc8f
94 | #8b4513
95 | #8b008b
96 | #8b0000
97 | #8a2be2
98 | #87cefa
99 | #87ceeb
100 | #808080
101 | #808080
102 | #808000
103 | #800080
104 | #800000
105 | #7fffd4
106 | #7fff00
107 | #7cfc00
108 | #7b68ee
109 | #778899
110 | #778899
111 | #708090
112 | #708090
113 | #6b8e23
114 | #6a5acd
115 | #696969
116 | #696969
117 | #66cdaa
118 | #6495ed
119 | #5f9ea0
120 | #556b2f
121 | #4b0082
122 | #48d1cc
123 | #483d8b
124 | #4682b4
125 | #4169e1
126 | #40e0d0
127 | #3cb371
128 | #32cd32
129 | #2f4f4f
130 | #2f4f4f
131 | #2e8b57
132 | #228b22
133 | #20b2aa
134 | #1e90ff
135 | #191970
136 | #00ffff
137 | #00ffff
138 | #00ff7f
139 | #00ff00
140 | #00fa9a
141 | #00ced1
142 | #00bfff
143 | #008b8b
144 | #008080
145 | #008000
146 | #006400
147 | #0000ff
148 | #0000cd
149 | #00008b
150 | #000080
151 | #000000
152 |
153 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/utils/AESUtils.java:
--------------------------------------------------------------------------------
1 | package com.nice.utils;
2 |
3 | import javax.crypto.*;
4 | import javax.crypto.spec.SecretKeySpec;
5 | import java.io.UnsupportedEncodingException;
6 | import java.security.InvalidKeyException;
7 | import java.security.Key;
8 | import java.security.NoSuchAlgorithmException;
9 | import java.util.UUID;
10 |
11 |
12 | public class AESUtils {
13 | static final String algorithmStr = "AES/ECB/PKCS5Padding";
14 |
15 | private static final Object TAG = "AES";
16 |
17 | static private KeyGenerator keyGen;
18 |
19 | static private Cipher cipher;
20 |
21 | static boolean isInited = false;
22 |
23 | private static void init() {
24 | try {
25 | /**为指定算法生成一个 KeyGenerator 对象。
26 | *此类提供(对称)密钥生成器的功能。
27 | *密钥生成器是使用此类的某个 getInstance 类方法构造的。
28 | *KeyGenerator 对象可重复使用,也就是说,在生成密钥后,
29 | *可以重复使用同一 KeyGenerator 对象来生成进一步的密钥。
30 | *生成密钥的方式有两种:与算法无关的方式,以及特定于算法的方式。
31 | *两者之间的惟一不同是对象的初始化:
32 | *与算法无关的初始化
33 | *所有密钥生成器都具有密钥长度 和随机源 的概念。
34 | *此 KeyGenerator 类中有一个 init 方法,它可采用这两个通用概念的参数。
35 | *还有一个只带 keysize 参数的 init 方法,
36 | *它使用具有最高优先级的提供程序的 SecureRandom 实现作为随机源
37 | *(如果安装的提供程序都不提供 SecureRandom 实现,则使用系统提供的随机源)。
38 | *此 KeyGenerator 类还提供一个只带随机源参数的 inti 方法。
39 | *因为调用上述与算法无关的 init 方法时未指定其他参数,
40 | *所以由提供程序决定如何处理将与每个密钥相关的特定于算法的参数(如果有)。
41 | *特定于算法的初始化
42 | *在已经存在特定于算法的参数集的情况下,
43 | *有两个具有 AlgorithmParameterSpec 参数的 init 方法。
44 | *其中一个方法还有一个 SecureRandom 参数,
45 | *而另一个方法将已安装的高优先级提供程序的 SecureRandom 实现用作随机源
46 | *(或者作为系统提供的随机源,如果安装的提供程序都不提供 SecureRandom 实现)。
47 | *如果客户端没有显式地初始化 KeyGenerator(通过调用 init 方法),
48 | *每个提供程序必须提供(和记录)默认初始化。
49 | */
50 | keyGen = KeyGenerator.getInstance("AES");
51 | } catch (NoSuchAlgorithmException e) {
52 | e.printStackTrace();
53 | }
54 | // 初始化此密钥生成器,使其具有确定的密钥长度。
55 | keyGen.init(128); //128位的AES加密
56 | try {
57 | // 生成一个实现指定转换的 Cipher 对象。
58 | cipher = Cipher.getInstance(algorithmStr);
59 | } catch (NoSuchAlgorithmException e) {
60 | e.printStackTrace();
61 | } catch (NoSuchPaddingException e) {
62 | e.printStackTrace();
63 | }
64 | //标识已经初始化过了的字段
65 | isInited = true;
66 | }
67 |
68 | private static byte[] genKey() {
69 | if (!isInited) {
70 | init();
71 | }
72 | //首先 生成一个密钥(SecretKey),
73 | //然后,通过这个秘钥,返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。
74 | return keyGen.generateKey().getEncoded();
75 | }
76 |
77 | private static byte[] encrypt(byte[] content, byte[] keyBytes) {
78 | byte[] encryptedText = null;
79 | if (!isInited) {
80 | init();
81 | }
82 | /**
83 | *类 SecretKeySpec
84 | *可以使用此类来根据一个字节数组构造一个 SecretKey,
85 | *而无须通过一个(基于 provider 的)SecretKeyFactory。
86 | *此类仅对能表示为一个字节数组并且没有任何与之相关联的钥参数的原始密钥有用
87 | *构造方法根据给定的字节数组构造一个密钥。
88 | *此构造方法不检查给定的字节数组是否指定了一个算法的密钥。
89 | */
90 | Key key = new SecretKeySpec(keyBytes, "AES");
91 | try {
92 | // 用密钥初始化此 cipher。
93 | cipher.init(Cipher.ENCRYPT_MODE, key);
94 | } catch (InvalidKeyException e) {
95 | e.printStackTrace();
96 | }
97 | try {
98 | //按单部分操作加密或解密数据,或者结束一个多部分操作。(不知道神马意思)
99 | encryptedText = cipher.doFinal(content);
100 | } catch (IllegalBlockSizeException e) {
101 | e.printStackTrace();
102 | } catch (BadPaddingException e) {
103 | e.printStackTrace();
104 | }
105 | return encryptedText;
106 | }
107 |
108 | private static byte[] encrypt(String content, String password) {
109 | try {
110 | byte[] keyStr = getKey(password);
111 | SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
112 | Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr
113 | byte[] byteContent = content.getBytes("utf-8");
114 | cipher.init(Cipher.ENCRYPT_MODE, key);// ʼ
115 | byte[] result = cipher.doFinal(byteContent);
116 | return result; //
117 | } catch (NoSuchAlgorithmException e) {
118 | e.printStackTrace();
119 | } catch (NoSuchPaddingException e) {
120 | e.printStackTrace();
121 | } catch (InvalidKeyException e) {
122 | e.printStackTrace();
123 | } catch (UnsupportedEncodingException e) {
124 | e.printStackTrace();
125 | } catch (IllegalBlockSizeException e) {
126 | e.printStackTrace();
127 | } catch (BadPaddingException e) {
128 | e.printStackTrace();
129 | }
130 | return null;
131 | }
132 |
133 | private static byte[] decrypt(byte[] content, String password) {
134 | try {
135 | byte[] keyStr = getKey(password);
136 | SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
137 | Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr
138 | cipher.init(Cipher.DECRYPT_MODE, key);// ʼ
139 | byte[] result = cipher.doFinal(content);
140 | return result; //
141 | } catch (NoSuchAlgorithmException e) {
142 | e.printStackTrace();
143 | } catch (NoSuchPaddingException e) {
144 | e.printStackTrace();
145 | } catch (InvalidKeyException e) {
146 | e.printStackTrace();
147 | } catch (IllegalBlockSizeException e) {
148 | e.printStackTrace();
149 | } catch (BadPaddingException e) {
150 | e.printStackTrace();
151 | }
152 | return null;
153 | }
154 |
155 | private static byte[] getKey(String password) {
156 | byte[] rByte = null;
157 | if (password != null) {
158 | rByte = password.getBytes();
159 | } else {
160 | rByte = new byte[24];
161 | }
162 | return rByte;
163 | }
164 |
165 | /**
166 | * 将二进制转换成16进制
167 | *
168 | * @param buf
169 | * @return
170 | */
171 | public static String parseByte2HexStr(byte buf[]) {
172 | StringBuffer sb = new StringBuffer();
173 | for (int i = 0; i < buf.length; i++) {
174 | String hex = Integer.toHexString(buf[i] & 0xFF);
175 | if (hex.length() == 1) {
176 | hex = '0' + hex;
177 | }
178 | sb.append(hex.toUpperCase());
179 | }
180 | return sb.toString();
181 | }
182 |
183 | /**
184 | * 将16进制转换为二进制
185 | *
186 | * @param hexStr
187 | * @return
188 | */
189 | public static byte[] parseHexStr2Byte(String hexStr) {
190 | if (hexStr.length() < 1)
191 | return null;
192 | byte[] result = new byte[hexStr.length() / 2];
193 | for (int i = 0; i < hexStr.length() / 2; i++) {
194 | int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
195 | int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
196 | 16);
197 | result[i] = (byte) (high * 16 + low);
198 | }
199 | return result;
200 | }
201 |
202 | //注意: 这里的password(秘钥必须是16位的)
203 | private static final String keyBytes = "TIKTOKKEY1368725";
204 |
205 | /**
206 | * 加密
207 | */
208 | public static String encode(String content) {
209 | //加密之后的字节数组,转成16进制的字符串形式输出
210 | return parseByte2HexStr(encrypt(content, keyBytes));
211 | }
212 |
213 | /**
214 | * 解密
215 | */
216 | public static String decode(String content) {
217 | //解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入
218 | byte[] b = decrypt(parseHexStr2Byte(content), keyBytes);
219 | return new String(b);
220 | }
221 |
222 | //测试用例
223 | public static void test1() {
224 | String content = "{\"activationCode\":\"004d68b7564c46d3929592ac51f700dd\",\"installationCode\":\"6db01b75-643e-428c-9597-82dab7d9077e\",\"deviceInfo\":\"OnePlus-OnePlus5-27\"}";
225 | String pStr = encode(content);
226 | System.out.println("加密前:" + content);
227 | System.out.println("加密后:" + pStr);
228 |
229 | String postStr = decode("58C7525204E788E1804C711D5DF6F8456DB606AD06B8784D37897F6578A9D6114CEFA6CE64B38A45F6B949C10A424684530723CA585177ADBBDC479B2778F0959D18864C5D614496740B764879CFE6C53A3E8AB77BF4AFB0E48A99BDD77ED38B9405788A1AD7616654CD7A02C37D324860BADD9D3E2ED9AD6F55F0B92EDE09C6506B25E57D76DD5B77F4E656A56B8F7BC1080AB3FBB6AD74E85CE4816519647C4BA25D2EFBE594E37BC37CDA8BDC72A62A285746C3B2AE482ADAD82ECE29C7FA746C30C1546105F3C5D8DC91BC59A0EFDA4E2A0FFDE7D99506529EB914FF69897D77F490514441C377A864C20BAC1D252DE425610F15A56FC4376A05C4C4C35045B72A6EDC75C5D6DE600479F1ECA58FBE5C92D4E3D5C03607233AD042F4F3E132692BB60D95FA8349D5AE80D606BEE8459F2A66F66B649759A4E16504688212CE2846546C295B1904257D6B92BC13F284A5BF7921E2C4BACE2472269DD22C9951AD18C3C4F73C419F7DADDADEF61E88167B28ECB378E5141D325E6BBDABCF21BC78C52D9D1ECBB6C635425519F74527B99078744189659AF0C4683E13F89F90489C746FE453A874893A76666F9F5246DC27768AAB5113A647ABE747ECBFEE9114ACC6F974C103AB3C04BE0700133E36DF4C2AA035DFF3EAC2A617A6BEE772073AD494D789EFAF7E6B0137DCAD6BD02EE0A47D551445798B17BA2C890C1DEF575244E70A2CA24D7A742DF77D9A4E4B9C669B875429FF8BED1353D50E7997828016A2F327E67B4A8FF23927D3E434ED000EC715AF0C5D6517B2E7F7131F544B98DF3B0DECECFB1B01EA2DF2760969B573DDCA16A19E3A4D6A731520B06258B741D49A37E307D3D461416371BC0CC2130BD4DE4E6E1E73092F74F7B4D8E3338ED9F3DDF7A2BACC69CA3BCE0D8B2952B186CB8977972F8CAF3A9365AFD4880108E28D28019DFBBFE7D1BB3300AA9372BCFE4B9FB98ECEADFA20E049CD4D50F1ADADABA71EE6556486CA3B615668098FE4CF394D56017E56AD41A97C3D3F6454062A43395E8D5194DDA0556749515AD54F00A33C3B8C61EABB294B59A6C2968C33178BF460A6A37FCE1463C2A6110A384E86B02490B850678A3A03B996815F08C6F38CEA51BF942DB59908B0B16FBB7D2B9C60BADD9D3E2ED9AD6F55F0B92EDE09C6506B25E57D76DD5B77F4E656A56B8F7B42B44E5011F137EE3B9BD84566FB4E5D214C5F4D19B9A5A9D527BE7595F6C5725062FE5E7D78695695335D9251B6BA2AA7F0D8CDD67D546F5EBCBCDB01EA52E866D8E1276111D728B4CA5A6DE660F1C8DF4C2AA035DFF3EAC2A617A6BEE772073AD494D789EFAF7E6B0137DCAD6BD02EE0A47D551445798B17BA2C890C1DEF57BA32A2DD1385240B75F94956CE39D74AD4AD8D4FFD8670267927379BB1AB49578C05FBED76F0BE4F27900BDD71F3AA8E1A3B1BB02B5FC08D7AA279B874763C84DF3B0DECECFB1B01EA2DF2760969B573DDCA16A19E3A4D6A731520B06258B741D49A37E307D3D461416371BC0CC2130BA7FD299CA681F18503F27809F91F88B5171B46A684F34F90534616509CD7B9C3AB05BBDC33889122F4905A6322F512E4CF404914D91B716CBD33956B4A61DD658904C5B605C918E967FCDD5AA3A5BAC7EDF4AFAD686FEDA12E173C8FEE2E7070AAE95A43C600A18C0EEB7CCE978B73A0FD51794268E8DA209C4010F2D4763D8CB814882DF2BAD9A2846752D2D9DA596CC82A9FCB8A2FA3D133451E49406F470872224A44247D0FAB683A60689BD693567675390AEE12A03436FA98517F30FEC62F57E87B8B6BA0DE845CC7C1471488327E97A3DC7EDF3EC726683339499DE0B1634A3B514C5E8DCE3AD5594751784BAD8744F163A506F3182A3DB2F763BBD15A0D1D4EFAA289A8BAC72A84051C2D1149B8824679AF3FE54347CB405CF38CAA22D2F7A240F452CA75A59D8AB281027A6327A6243C4551372F21FF3DAAABB649327B640056BC6C8800C6F07B1399D0B540B2C0767DF3591592CC40B049B4C87DFBEE360B809EF984EADD31B508C31D0339B93E065517FECC64BC6B4A4BA2B64FF4");
230 | System.out.println("解密后:" + postStr);
231 | }
232 |
233 | public static void main(String[] args) {
234 | test1();
235 | System.out.println(UUID.randomUUID().toString());
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
27 |
28 |
38 |
39 |
40 |
41 |
45 |
46 |
50 |
51 |
55 |
56 |
60 |
61 |
67 |
68 |
74 |
75 |
76 |
77 |
83 |
84 |
85 |
91 |
92 |
97 |
98 |
101 |
102 |
107 |
108 |
113 |
114 |
115 |
116 |
120 |
121 |
126 |
127 |
132 |
133 |
134 |
138 |
139 |
144 |
145 |
150 |
151 |
152 |
156 |
157 |
162 |
163 |
168 |
169 |
170 |
174 |
175 |
181 |
182 |
186 |
187 |
192 |
193 |
197 |
198 |
199 |
200 |
207 |
208 |
209 |
210 |
216 |
217 |
221 |
222 |
227 |
228 |
232 |
233 |
234 |
241 |
242 |
247 |
248 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
291 |
292 |
293 |
294 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
314 |
315 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/service/TikTokAccessibilityService.java:
--------------------------------------------------------------------------------
1 | package com.nice.service;
2 |
3 | import android.accessibilityservice.AccessibilityService;
4 | import android.content.ClipData;
5 | import android.content.ClipboardManager;
6 | import android.content.Context;
7 | import android.os.Looper;
8 | import android.util.Log;
9 | import android.view.accessibility.AccessibilityEvent;
10 | import android.view.accessibility.AccessibilityNodeInfo;
11 | import android.widget.Toast;
12 |
13 | import com.nice.config.Config;
14 | import com.nice.utils.PerformClickUtils;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import java.util.Map;
19 | import java.util.Random;
20 |
21 | public class TikTokAccessibilityService extends AccessibilityService {
22 |
23 | public static List privateLetterList = new ArrayList<>();
24 | public static List commentPrivateLetterList = new ArrayList<>();
25 | public static Integer attentionCount = 0;
26 | public static Integer commentPrivatelyCount = 0;
27 | //操作状态 正在私信/关注
28 | public static Boolean executing = false;
29 |
30 | @Override
31 | protected void onServiceConnected() {
32 | toast("服务已开启!");
33 | super.onServiceConnected();
34 | }
35 |
36 | @Override
37 | public void onAccessibilityEvent(AccessibilityEvent event) {
38 |
39 | if (Config.getInstance(this).getActivated()) {
40 |
41 | if (Config.getInstance(this).getStatus()) {
42 | if (Config.getInstance(this).getOption().equals(Config.CONCERN)) {
43 | synchronized (TikTokAccessibilityService.class) {
44 | //当没有关注才进行节点检索
45 | if (!executing) {
46 | AccessibilityNodeInfo accessibilityNodeInfo = this.getRootInActiveWindow();
47 | //TODO 关注/取消按钮
48 | final List attentionBtns = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(Config.getInstance(this).getViewIdByVersionMap().get(Config.ATTENTION_BTN));
49 | if (!attentionBtns.isEmpty()) {
50 | new Thread(new Runnable() {
51 | @Override
52 | public void run() {
53 | //改变当前状态为正在关注
54 | executing = true;
55 | //循环当页已获取用户列表
56 | attention(attentionBtns);
57 | //翻页
58 | if (Config.getInstance(TikTokAccessibilityService.this).getStatus()) {
59 | //TODO 用户列表背景
60 | if (!PerformClickUtils.findViewIdAndScroll(TikTokAccessibilityService.this, Config.getInstance(TikTokAccessibilityService.this).getViewIdByVersionMap().get(Config.USER_LIST_BG))) {
61 | toast("脚本已执行完毕");
62 | }
63 | }
64 | executing = false;
65 | }
66 | }).start();
67 | //清理节点
68 | accessibilityNodeInfo.recycle();
69 | }
70 | }
71 | }
72 | } else if (Config.getInstance(this).getOption().equals(Config.CANCEL_CONCERN)) {
73 | synchronized (TikTokAccessibilityService.class) {
74 | if (!executing) {
75 | AccessibilityNodeInfo accessibilityNodeInfo = this.getRootInActiveWindow();
76 | //TODO 关注/取消按钮
77 | final List cancelAttentionBtns = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(Config.getInstance(this).getViewIdByVersionMap().get(Config.ATTENTION_BTN));
78 | if (!cancelAttentionBtns.isEmpty()) {
79 | new Thread(new Runnable() {
80 | @Override
81 | public void run() {
82 | executing = true;
83 | //循环当页已获取用户列表
84 | cancelAttention(cancelAttentionBtns);
85 | //翻页
86 | if (Config.getInstance(TikTokAccessibilityService.this).getStatus()) {
87 | //TODO 用户列表背景
88 | if (!PerformClickUtils.findViewIdAndScroll(TikTokAccessibilityService.this, Config.getInstance(TikTokAccessibilityService.this).getViewIdByVersionMap().get(Config.USER_LIST_BG))) {
89 | toast("脚本已执行完毕");
90 | }
91 | }
92 | executing = false;
93 | }
94 | }).start();
95 | //清理节点
96 | accessibilityNodeInfo.recycle();
97 | }
98 | }
99 | }
100 | } else if (Config.getInstance(this).getOption().equals(Config.PRIVATELY)) {
101 | // String currentWindowActivity = event.getClassName().toString();
102 | // if ("com.ss.android.ugc.aweme.main.MainActivity".equals(currentWindowActivity)) {
103 | // PerformClickUtils.findViewIdAndClick(this, "com.ss.android.ugc.aweme:id/a_7");
104 | // }
105 | synchronized (TikTokAccessibilityService.class) {
106 | if (!executing) {
107 | AccessibilityNodeInfo accessibilityNodeInfo = this.getRootInActiveWindow();
108 | //TODO 列表用户名
109 | final List privatelyViews = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(Config.getInstance(this).getViewIdByVersionMap().get(Config.LIST_USER_NAME));
110 | if (!privatelyViews.isEmpty()) {
111 |
112 | new Thread(new Runnable() {
113 | @Override
114 | public void run() {
115 | executing = true;
116 | Looper.prepare();
117 | //循环当页已获取用户列表
118 | privately(privatelyViews);
119 | //翻页
120 | if (Config.getInstance(TikTokAccessibilityService.this).getStatus()) {
121 | //TODO 用户列表背景
122 | if (!PerformClickUtils.findViewIdAndScroll(TikTokAccessibilityService.this, Config.getInstance(TikTokAccessibilityService.this).getViewIdByVersionMap().get(Config.USER_LIST_BG))) {
123 | toast("脚本已执行完毕");
124 | }
125 | }
126 | executing = false;
127 | Looper.loop();
128 | }
129 | }).start();
130 | //清理节点
131 | accessibilityNodeInfo.recycle();
132 | }
133 | }
134 | }
135 | } else if (Config.getInstance(this).getOption().equals(Config.COMMENT_PRIVATELY)) {
136 | synchronized (TikTokAccessibilityService.class) {
137 | if (!executing) {
138 | // try {
139 | // PerformClickUtils.JumpViewByViewId(this, "com.ss.android.ugc.aweme:id/a29", "com.ss.android.ugc.aweme:id/yd", 500);
140 | // } catch (InterruptedException e) {
141 | // e.printStackTrace();
142 | // }
143 | final List commentViews = getRootInActiveWindow().findAccessibilityNodeInfosByViewId("com.ss.android.ugc.aweme:id/yd");
144 | if (!commentViews.isEmpty()) {
145 | new Thread(new Runnable() {
146 | @Override
147 | public void run() {
148 | executing = true;
149 | Looper.prepare();
150 | commentPrivately(commentViews);
151 | //翻页
152 | if (Config.getInstance(TikTokAccessibilityService.this).getStatus()) {
153 | if (!PerformClickUtils.findViewIdAndScroll(TikTokAccessibilityService.this, "com.ss.android.ugc.aweme:id/rw") || commentPrivatelyCount > 50) {
154 | toast("脚本已执行完毕");
155 | }
156 | }
157 | executing = false;
158 | Looper.loop();
159 | }
160 | }).start();
161 | }
162 | }
163 | }
164 | }
165 |
166 | }
167 | }
168 |
169 | }
170 |
171 | @Override
172 | public void onInterrupt() {
173 | toast("服务已中断!");
174 | }
175 |
176 | public void toast(final String msg) {
177 | new Thread(new Runnable() {
178 | public void run() {
179 | Looper.prepare();
180 | Toast.makeText(TikTokAccessibilityService.this, msg, Toast.LENGTH_SHORT).show();
181 | Looper.loop();
182 | }
183 | }).start();
184 | }
185 |
186 | /**
187 | * 视频评论私信
188 | */
189 | public synchronized void commentPrivately(List commentViews) {
190 |
191 | if (Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.COMMENT_PRIVATELY)) {
192 | try {
193 | Thread.sleep(500);
194 | } catch (InterruptedException e) {
195 | e.printStackTrace();
196 | }
197 | for (AccessibilityNodeInfo commentView : commentViews) {
198 | try {
199 | if (Config.getInstance(this).getStatus() && !commentPrivateLetterList.contains(commentView.getParent().getChild(1).getText().toString())) {
200 | Thread.sleep(1000);
201 | Log.i("私信评论:", commentView.getParent().getChild(1).getText().toString());
202 | PerformClickUtils.JumpViewByViewInfo(this, commentView.getParent(), "com.ss.android.ugc.aweme:id/hg", 500);
203 | if (!getRootInActiveWindow().findAccessibilityNodeInfosByText("删除").isEmpty()) {
204 | PerformClickUtils.findTextAndClick(this, "复制");
205 | Thread.sleep(1000);
206 | } else {
207 | PerformClickUtils.JumpViewByViewText(this, "私信回复", "com.ss.android.ugc.aweme:id/a54", 500);
208 | PerformClickUtils.findViewIdAndClick(this, "com.ss.android.ugc.aweme:id/a54");
209 | Thread.sleep(500);
210 | setPrivatelyContent();
211 | getRootInActiveWindow().findAccessibilityNodeInfosByViewId("com.ss.android.ugc.aweme:id/a54").get(0).performAction(AccessibilityNodeInfo.ACTION_PASTE);
212 | PerformClickUtils.findViewIdAndClick(this, "com.ss.android.ugc.aweme:id/a57");
213 | Thread.sleep(1000);
214 | commentPrivateLetterList.add(commentView.getParent().getChild(1).getText().toString());
215 | commentPrivatelyCount++;
216 | }
217 | Thread.sleep(Config.getInstance(this).getPrivatelySpeed() + Math.round(2000 * Math.random()));
218 | }
219 | } catch (Exception e) {
220 | e.printStackTrace();
221 | }
222 | }
223 | try {
224 | Thread.sleep(2000);
225 | } catch (InterruptedException e) {
226 | e.printStackTrace();
227 | }
228 |
229 | }
230 |
231 | }
232 |
233 | /**
234 | * 关注
235 | *
236 | * @param attentionBtns
237 | */
238 | public synchronized void attention(List attentionBtns) {
239 |
240 | if (Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.CONCERN) && !attentionBtns.isEmpty()) {
241 | try {
242 | Thread.sleep(500);
243 | } catch (InterruptedException e) {
244 | e.printStackTrace();
245 | }
246 | for (AccessibilityNodeInfo concernBtn : attentionBtns) {
247 | Log.i("执行操作:", "关注");
248 | if (concernBtn.getText().toString().equals("关注") && Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.CONCERN) && attentionCount <= 200) {
249 | concernBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK);
250 | attentionCount++;
251 | toast("已关注" + attentionCount + "人");
252 | try {
253 | //关注停顿
254 | Thread.sleep(Config.getInstance(this).getAttentionSpeed() + Math.round(2000 * Math.random()));
255 | } catch (InterruptedException e) {
256 | e.printStackTrace();
257 | }
258 | }
259 | }
260 | }
261 | }
262 |
263 | /**
264 | * 取消关注
265 | *
266 | * @param attentionBtns
267 | */
268 | public synchronized void cancelAttention(List attentionBtns) {
269 |
270 | if (Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.CANCEL_CONCERN) && !attentionBtns.isEmpty()) {
271 | try {
272 | Thread.sleep(500);
273 | } catch (InterruptedException e) {
274 | e.printStackTrace();
275 | }
276 | for (AccessibilityNodeInfo concernBtn : attentionBtns) {
277 | Log.i("执行操作:", "取消关注");
278 | if ((concernBtn.getText().toString().equals("已关注") || concernBtn.getText().toString().equals("互相关注")) && Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.CANCEL_CONCERN)) {
279 | concernBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK);
280 | attentionCount++;
281 | toast("已取消关注" + attentionCount + "人");
282 | try {
283 | //关注停顿
284 | Thread.sleep(Config.getInstance(this).getAttentionSpeed() + Math.round(2000 * Math.random()));
285 | } catch (InterruptedException e) {
286 | e.printStackTrace();
287 | }
288 | }
289 | }
290 | }
291 | }
292 |
293 | /**
294 | * 私信
295 | *
296 | * @param privatelyViews
297 | */
298 | public synchronized void privately(List privatelyViews) {
299 |
300 | Map viewIdMap = Config.getInstance(this).getViewIdByVersionMap();
301 |
302 | if (Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.PRIVATELY) && !privatelyViews.isEmpty()) {
303 | try {
304 | Thread.sleep(500);
305 | } catch (InterruptedException e) {
306 | e.printStackTrace();
307 | }
308 |
309 | for (AccessibilityNodeInfo info : privatelyViews) {
310 | try {
311 | if (Config.getInstance(this).getStatus() && Config.getInstance(this).getOption().equals(Config.PRIVATELY) && !privateLetterList.contains(info.getText().toString()) && info.getParent().getChildCount() > 1) {
312 |
313 | Thread.sleep(500);
314 |
315 | int count = 0;
316 | Log.i("昵称:", info.getText().toString() + "--点击主页");
317 | //TODO 主页右上角更多按钮
318 | PerformClickUtils.JumpViewByViewInfo(this, info, viewIdMap.get(Config.USER_HP_MORE), 500);
319 | Log.i("昵称:", info.getText().toString() + "--进入更多界面");
320 | //TODO 主页右上角更多按钮 更多页面对话按钮
321 | PerformClickUtils.JumpViewByViewId(this, viewIdMap.get(Config.USER_HP_MORE), viewIdMap.get(Config.MORE_TALK_BTN), 500);
322 | Log.i("昵称:", info.getText().toString() + "--进入私信界面");
323 | //TODO 更多页面对话按钮 发送消息EditText
324 | PerformClickUtils.JumpViewByViewId(this, viewIdMap.get(Config.MORE_TALK_BTN), viewIdMap.get(Config.SEND_MSG_ET), 500);
325 |
326 |
327 | //检测是否已经回复过
328 | boolean replied = false;
329 | //已经私信过的不操作
330 | while (!replied && Config.getInstance(this).getStatus()) {
331 | setPrivatelyContent();
332 | Log.i("昵称:", info.getText().toString() + "--私信");
333 | //TODO 发送消息EditText
334 | PerformClickUtils.findViewIdAndClick(this, viewIdMap.get(Config.SEND_MSG_ET));
335 | Thread.sleep(500);
336 | count++;
337 | if (count >= 5) {
338 | break;
339 | }
340 |
341 | int sendCount = 0;
342 | // 模拟粘贴
343 | List bcn;
344 | do {
345 | Log.i("昵称:", info.getText().toString() + "--寻找输入框");
346 | //TODO 发送消息EditText
347 | bcn = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(viewIdMap.get(Config.SEND_MSG_ET));
348 | Thread.sleep(500);
349 | sendCount++;
350 | if (sendCount >= 5) {
351 | break;
352 | }
353 | }
354 | while (bcn.isEmpty() && Config.getInstance(this).getStatus());
355 | Thread.sleep(500);
356 |
357 | Log.i("昵称:", info.getText().toString() + "--发送私信");
358 | bcn.get(0).performAction(AccessibilityNodeInfo.ACTION_PASTE);
359 | //TODO 发送按钮
360 | PerformClickUtils.findViewIdAndClick(this, viewIdMap.get(Config.SEND_MSG_BTN));
361 | Thread.sleep(500);
362 |
363 | for (String s : Config.getInstance(this).getPrivatelyContent()) {
364 | if (!getRootInActiveWindow().findAccessibilityNodeInfosByText(s).isEmpty()) {
365 | replied = true;
366 | }
367 | }
368 | }
369 | Log.i("昵称:", info.getText().toString() + "--返回更多页面");
370 | //TODO 对话界面返回按钮 更多页面对话按钮
371 | PerformClickUtils.JumpViewByViewId(this, viewIdMap.get(Config.TALK_BACK), viewIdMap.get(Config.MORE_TALK_BTN), 2000);
372 | Log.i("昵称:", info.getText().toString() + "--返回主页");
373 | //TODO 更多页面返回按钮 主页右上角更多按钮
374 | PerformClickUtils.JumpViewByViewId(this, viewIdMap.get(Config.MORE_BACK), viewIdMap.get(Config.USER_HP_MORE), 2000);
375 | Log.i("昵称:", info.getText().toString() + "--返回列表");
376 | //TODO 主页返回按钮 用户列表背景
377 | PerformClickUtils.JumpViewByViewId(this, viewIdMap.get(Config.USER_HP_BACK), viewIdMap.get(Config.USER_LIST_BG), 2000);
378 |
379 | //放入已私信列表
380 | privateLetterList.add(info.getText().toString());
381 | toast("已私信" + privateLetterList.size() + "人");
382 | Thread.sleep(Config.getInstance(this).getPrivatelySpeed() + Math.round(2000 * Math.random()));
383 | }
384 | } catch (Exception e) {
385 | e.printStackTrace();
386 | break;
387 | }
388 | }
389 | }
390 | try {
391 | Thread.sleep(1000);
392 | } catch (InterruptedException e) {
393 | e.printStackTrace();
394 | }
395 | }
396 |
397 |
398 | private void setPrivatelyContent() {
399 |
400 | //获取设置的私信内容
401 | String[] privatelyContent = Config.getInstance(this).getPrivatelyContent();
402 | int max = privatelyContent.length;
403 | int min = 0;
404 | Random random = new Random();
405 | int i = random.nextInt(max) % (max - min + 1) + min;
406 | //获取剪贴板管理器:
407 | ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
408 | // 创建普通字符型ClipData
409 | ClipData mClipData = ClipData.newPlainText("Label", privatelyContent[i]);
410 | // 将ClipData内容放到系统剪贴板里。
411 | cm.setPrimaryClip(mClipData);
412 | }
413 |
414 | }
415 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nice/tiktoktool/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.nice.tiktoktool;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.app.AppOpsManager;
6 | import android.content.ComponentName;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.graphics.Color;
10 | import android.graphics.drawable.Drawable;
11 | import android.net.Uri;
12 | import android.os.*;
13 | import android.provider.Settings;
14 | import android.support.design.widget.TextInputEditText;
15 | import android.text.Editable;
16 | import android.text.TextUtils;
17 | import android.text.TextWatcher;
18 | import android.util.Log;
19 | import android.view.View;
20 | import android.widget.*;
21 | import com.alibaba.fastjson.JSONArray;
22 | import com.alibaba.fastjson.JSONObject;
23 | import com.nice.config.Config;
24 | import com.nice.entity.ActivationCode;
25 | import com.nice.entity.ViewId;
26 | import com.nice.service.MyService;
27 | import com.nice.utils.AESUtils;
28 | import com.nice.utils.ApplicationUtil;
29 | import com.nice.utils.JumpPermissionManagement;
30 | import com.nice.utils.PerformClickUtils;
31 | import okhttp3.*;
32 |
33 | import java.io.IOException;
34 | import java.lang.reflect.Method;
35 | import java.text.SimpleDateFormat;
36 | import java.util.*;
37 |
38 | public class MainActivity extends Activity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener, AdapterView.OnItemSelectedListener {
39 |
40 |
41 | private Switch openPermission, openServiceBtn;
42 | private Button openTiktokBtn;
43 | private TextView attentionSpeedTv, privatelySpeedTv, activationStateTv2, activationEndTime;
44 | private LinearLayout attentionSetting, privatelySetting;
45 | private TextInputEditText privatelyContent;
46 | private SeekBar attentionSpeedSb, privatelySpeedSb;
47 | private ImageView usrSettingBtn;
48 | private ProgressBar progressBar;
49 | private Spinner tiktokVersionSpinner, optionSpinner;
50 | private ArrayAdapter adapter;
51 |
52 | private List versionList;
53 |
54 | /*构造一个Handler,主要作用有:1)供非UI线程发送Message 2)处理Message并完成UI更新*/
55 | public Handler uiHandler = new Handler(new Handler.Callback() {
56 | @Override
57 | public boolean handleMessage(Message msg) {
58 | switch (msg.what) {
59 | case 200:
60 | progressBar.setVisibility(View.GONE);
61 | Bundle bundle = msg.getData();
62 | JSONObject data = JSONObject.parseObject(bundle.getString("data"));
63 | if (data.getInteger("code") == 0) {
64 | if (data.getInteger("valid") == 1) {
65 | ActivationCode activationCode = JSONObject.toJavaObject(data.getJSONObject("data"), ActivationCode.class);
66 | //获得viewId信息
67 | List viewIds = JSONArray.parseArray(data.getString("viewIds"), ViewId.class);
68 | Config.getInstance(getApplicationContext()).setViewIds(viewIds);
69 | Config.getInstance(getApplicationContext()).setActivated(true);
70 | Config.getInstance(getApplicationContext()).setActivationCode(activationCode.getActivationCode());
71 | Config.getInstance(getApplicationContext()).setEndTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(activationCode.getEndTime()));
72 |
73 | //获得版本号
74 | versionList = new ArrayList<>();
75 | for (ViewId viewId : viewIds) {
76 | if (!TextUtils.isEmpty(viewId.getVersion()) && !versionList.contains(viewId.getVersion())) {
77 | versionList.add(viewId.getVersion());
78 | }
79 | }
80 | Collections.reverse(versionList);
81 |
82 | //绑定版本下拉框数据
83 | adapter = new ArrayAdapter<>(getApplication(),
84 | android.R.layout.simple_spinner_dropdown_item, versionList);
85 | tiktokVersionSpinner.setAdapter(adapter);
86 | //请求viewIds完毕后再监听version下拉框
87 | tiktokVersionSpinner.setOnItemSelectedListener(MainActivity.this);
88 | } else {
89 | Config.getInstance(getApplicationContext()).setActivated(false);
90 | Config.getInstance(getApplicationContext()).setEndTime(" - ");
91 | }
92 | } else {
93 | Config.getInstance(getApplicationContext()).setActivated(false);
94 | Config.getInstance(getApplicationContext()).setEndTime(" - ");
95 | }
96 | setActiviteLogo();
97 | break;
98 | case 500:
99 | progressBar.setVisibility(View.GONE);
100 | Config.getInstance(getApplicationContext()).setActivated(false);
101 | Config.getInstance(getApplicationContext()).setEndTime(" - ");
102 | Toast.makeText(getApplicationContext(), "连接服务器失败!", Toast.LENGTH_LONG).show();
103 | setActiviteLogo();
104 | break;
105 | default:
106 | break;
107 |
108 | }
109 | return false;
110 | }
111 | });
112 |
113 | @Override
114 | protected void onCreate(Bundle savedInstanceState) {
115 | super.onCreate(savedInstanceState);
116 | setContentView(R.layout.activity_main);
117 | //初始化ui
118 | init();
119 |
120 | //绑定操作下拉框数据
121 | adapter = new ArrayAdapter<>(this,
122 | android.R.layout.simple_spinner_dropdown_item, getOptionSource());
123 | optionSpinner.setAdapter(adapter);
124 |
125 | //启动悬浮窗
126 | startService(new Intent(this, MyService.class).putExtra(MyService.ACTION, MyService.SHOW));
127 |
128 | //请求设备信息
129 | requestDeviceInfo();
130 |
131 | }
132 |
133 | public void init() {
134 | openPermission = findViewById(R.id.open_permission_btn);
135 | openServiceBtn = findViewById(R.id.open_accessibility_btn);
136 | openTiktokBtn = findViewById(R.id.open_tiktok_btn);
137 | attentionSetting = findViewById(R.id.attention_setting);
138 | privatelySetting = findViewById(R.id.privately_setting);
139 | privatelyContent = findViewById(R.id.privately_content);
140 | attentionSpeedTv = findViewById(R.id.attention_speed_tv);
141 | attentionSpeedSb = findViewById(R.id.attention_speed_sb);
142 | usrSettingBtn = findViewById(R.id.usr_setting_btn);
143 | privatelySpeedTv = findViewById(R.id.privately_speed_tv);
144 | privatelySpeedSb = findViewById(R.id.privately_speed_sb);
145 | progressBar = findViewById(R.id.progress_bar);
146 | activationStateTv2 = findViewById(R.id.activation_state_tv2);
147 | activationEndTime = findViewById(R.id.activation_end_time);
148 | optionSpinner = findViewById(R.id.option_spinner);
149 | tiktokVersionSpinner = findViewById(R.id.tiktok_version_spinner);
150 |
151 | changeStatus();
152 |
153 | openServiceBtn.setOnCheckedChangeListener(this);
154 | openPermission.setOnCheckedChangeListener(this);
155 | openTiktokBtn.setOnClickListener(this);
156 | usrSettingBtn.setOnClickListener(this);
157 | optionSpinner.setOnItemSelectedListener(this);
158 |
159 | attentionSpeedSb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
160 | @Override
161 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
162 | attentionSpeedTv.setText("(" + i + "~" + (i + 2) + "秒/个)");
163 | if (i < 1) {
164 | attentionSpeedSb.setProgress(1);
165 | }
166 | }
167 |
168 | @Override
169 | public void onStartTrackingTouch(SeekBar seekBar) {
170 | }
171 |
172 | @Override
173 | public void onStopTrackingTouch(SeekBar seekBar) {
174 | Config.getInstance(MainActivity.this).setAttentionSpeed((long) seekBar.getProgress());
175 | }
176 | });
177 |
178 | privatelySpeedSb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
179 | @Override
180 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
181 | privatelySpeedTv.setText("(" + i + "~" + (i + 2) + "秒/个)");
182 | if (i < 1) {
183 | privatelySpeedSb.setProgress(1);
184 | }
185 | }
186 |
187 | @Override
188 | public void onStartTrackingTouch(SeekBar seekBar) {
189 |
190 | }
191 |
192 | @Override
193 | public void onStopTrackingTouch(SeekBar seekBar) {
194 | Config.getInstance(MainActivity.this).setPrivatelySpeed((long) seekBar.getProgress());
195 | }
196 | });
197 |
198 | privatelyContent.addTextChangedListener(new TextWatcher() {
199 | @Override
200 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
201 |
202 | }
203 |
204 | @Override
205 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
206 |
207 | }
208 |
209 | @Override
210 | public void afterTextChanged(Editable editable) {
211 | Config.getInstance(MainActivity.this).setPrivatelyContent(editable.toString());
212 | }
213 | });
214 | }
215 |
216 | public List getOptionSource() {
217 | List list = new ArrayList<>();
218 | list.add("关注");
219 | list.add("取消关注");
220 | list.add("私信粉丝");
221 | list.add("私信关注");
222 | list.add("私信他人粉丝");
223 | list.add("私信他人关注");
224 | // list.add("私信评论用户");
225 | return list;
226 | }
227 |
228 | public void setActiviteLogo() {
229 | Drawable drawable;
230 | if (Config.getInstance(this).getActivated()) {
231 | drawable = getResources().getDrawable(R.mipmap.activated);
232 | activationStateTv2.setText("已激活");
233 | activationStateTv2.setTextColor(Color.parseColor("#e91e63"));
234 | activationEndTime.setText(Config.getInstance(this).getEndTime() + " 到期");
235 | } else {
236 | drawable = getResources().getDrawable(R.mipmap.not_active);
237 | activationStateTv2.setText("未激活");
238 | activationStateTv2.setTextColor(Color.GRAY);
239 | activationEndTime.setText("");
240 | }
241 | drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
242 | activationStateTv2.setCompoundDrawables(drawable, null, null, null);
243 |
244 | }
245 |
246 | public void requestDeviceInfo() {
247 |
248 | progressBar.setVisibility(View.VISIBLE);
249 |
250 | MediaType mediaType = MediaType.parse("application/json; charset=utf-8");//"类型,字节码"
251 |
252 | JSONObject encryptedDataEntity = new JSONObject();
253 | JSONObject jsonObject = new JSONObject();
254 | jsonObject.put("activationCode", Config.getInstance(this).getActivationCode());
255 | jsonObject.put("InstallationCode", ApplicationUtil.id(this));
256 | jsonObject.put("deviceInfo", Config.DEVICE_INFO);
257 | encryptedDataEntity.put("data", AESUtils.encode(jsonObject.toString()));
258 | //json字符串
259 | String value = String.valueOf(encryptedDataEntity);
260 | //1.创建OkHttpClient对象
261 | OkHttpClient okHttpClient = new OkHttpClient();
262 | //2.通过RequestBody.create 创建requestBody对象
263 | RequestBody requestBody = RequestBody.create(mediaType, value);
264 | //3.创建Request对象,设置URL地址,将RequestBody作为post方法的参数传入
265 | Request request = new Request.Builder().url(Config.CODE_VALIDATE_URL).post(requestBody).build();
266 | //4.创建一个call对象,参数就是Request请求对象
267 | Call call = okHttpClient.newCall(request);
268 | //5.请求加入调度,重写回调方法
269 | call.enqueue(new Callback() {
270 |
271 | @Override
272 | public void onFailure(Call call, IOException e) {
273 | e.printStackTrace();
274 | new Thread() {
275 | public void run() {
276 | uiHandler.sendEmptyMessage(500);
277 | }
278 | }.start();
279 | }
280 |
281 | @Override
282 | public void onResponse(Call call, Response response) throws IOException {
283 | final JSONObject encryptedData = JSONObject.parseObject(response.body().string());
284 | new Thread() {
285 | public void run() {
286 | Bundle bundle = new Bundle();
287 | bundle.putString("data", AESUtils.decode(encryptedData.getString("data")));
288 | Message message = new Message();
289 | message.what = 200;
290 | message.setData(bundle);
291 | uiHandler.sendMessage(message);
292 | }
293 | }.start();
294 | }
295 | });
296 | }
297 |
298 |
299 | @Override
300 | public void onClick(View view) {
301 | if (view.getId() == R.id.open_tiktok_btn) {
302 | if (Config.getInstance(this).getActivated()) {
303 | //打开抖音app
304 | Intent intent = new Intent(Intent.ACTION_MAIN);
305 | ComponentName componentName = new ComponentName("com.ss.android.ugc.aweme", "com.ss.android.ugc.aweme.main.MainActivity");
306 | intent.setComponent(componentName);
307 | startActivity(intent);
308 | } else {
309 | Toast.makeText(this, "软件未激活!", Toast.LENGTH_LONG).show();
310 | }
311 |
312 | }
313 |
314 | if (view.getId() == R.id.usr_setting_btn) {
315 | Intent intent = new Intent(MainActivity.this, UserSettingActivity.class);
316 | startActivity(intent);
317 | }
318 | }
319 |
320 | @Override
321 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
322 |
323 | if (compoundButton.getId() == R.id.open_accessibility_btn) {
324 | if (b) {
325 | Toast.makeText(MainActivity.this, "请打开[抖音引流脚本]辅助服务!", Toast.LENGTH_SHORT).show();
326 | startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
327 | }
328 | }
329 | if (compoundButton.getId() == R.id.open_permission_btn) {
330 | if (b) {
331 | openSetting();
332 | }
333 | }
334 | }
335 |
336 | /**
337 | * 打开应用设置
338 | */
339 |
340 | public void openAppSetting() {
341 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
342 | Uri uri = Uri.fromParts("package", getPackageName(), null);
343 | intent.setData(uri);
344 | startActivityForResult(intent, 11);
345 | Log.e("", "启动悬浮窗界面");
346 | }
347 |
348 | /**
349 | * 打开权限设置界面
350 | */
351 | public void openSetting() {
352 | try {
353 | if (JumpPermissionManagement.gotoPermissionSetting(this)) {
354 | openAppSetting();
355 | } else {
356 | Toast.makeText(MainActivity.this, "请授权应用[允许出现在其他应用上]权限!", Toast.LENGTH_SHORT).show();
357 | }
358 | } catch (Exception e) {
359 | openAppSetting();
360 | }
361 |
362 | }
363 |
364 | /**
365 | * 判断悬浮窗权限
366 | *
367 | * @param context
368 | * @return
369 | */
370 | @TargetApi(Build.VERSION_CODES.KITKAT)
371 | public static boolean isFloatWindowOpAllowed(Context context) {
372 | final int version = Build.VERSION.SDK_INT;
373 | if (version >= 19) {
374 | return checkOp(context, 24); // AppOpsManager.OP_SYSTEM_ALERT_WINDOW
375 | } else {
376 | if ((context.getApplicationInfo().flags & 1 << 27) == 1 << 27) {
377 | return true;
378 | } else {
379 | return false;
380 | }
381 | }
382 | }
383 |
384 |
385 | @TargetApi(Build.VERSION_CODES.KITKAT)
386 | public static boolean checkOp(Context context, int op) {
387 | final int version = Build.VERSION.SDK_INT;
388 |
389 | if (version >= 19) {
390 | AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
391 | try {
392 | Method method = manager.getClass().getDeclaredMethod("checkOp", int.class, int.class, String.class);
393 | int property = (Integer) method.invoke(manager, op,
394 | Binder.getCallingUid(), context.getPackageName());
395 |
396 | if (AppOpsManager.MODE_ALLOWED == property) {
397 | return true;
398 | } else {
399 | return false;
400 | }
401 | } catch (Exception e) {
402 | e.printStackTrace();
403 | }
404 | } else {
405 | Log.e("399", "Below API 19 cannot invoke!");
406 | }
407 | return false;
408 | }
409 |
410 |
411 | private void changeStatus() {
412 |
413 | setActiviteLogo();
414 |
415 | if (PerformClickUtils.isStartAccessibilityService(this)) {
416 | openServiceBtn.setChecked(true);
417 | } else {
418 | openServiceBtn.setChecked(false);
419 | }
420 | if (isFloatWindowOpAllowed(this)) {
421 | openPermission.setChecked(true);
422 | } else {
423 | openPermission.setChecked(false);
424 | }
425 |
426 | }
427 |
428 | @Override
429 | protected void onResume() {
430 | super.onResume();
431 | changeStatus();
432 | }
433 |
434 | @Override
435 | protected void onPause() {
436 | super.onPause();
437 | }
438 |
439 | @Override
440 | public void onItemSelected(AdapterView> adapterView, View view, int i, long l) {
441 | if (adapterView.getId() == R.id.option_spinner) {
442 | if (i == 0) {
443 | Config.getInstance(this).setOption(Config.CONCERN);
444 | attentionSetting.setVisibility(View.VISIBLE);
445 | privatelySetting.setVisibility(View.GONE);
446 | //速度显示
447 | attentionSpeedTv.setText("(" + Config.getInstance(this).getAttentionSpeed() / 1000 + "~" + (Config.getInstance(this).getAttentionSpeed() / 1000 + 2) + "秒/个)");
448 | attentionSpeedSb.setProgress((int) (Config.getInstance(this).getAttentionSpeed() / 1000));
449 | privatelySpeedTv.setText("(" + Config.getInstance(this).getPrivatelySpeed() / 1000 + "~" + (Config.getInstance(this).getPrivatelySpeed() / 1000 + 2) + "秒/个)");
450 | privatelySpeedSb.setProgress((int) (Config.getInstance(this).getPrivatelySpeed() / 1000));
451 | }
452 | if (i == 1) {
453 | Config.getInstance(this).setOption(Config.CANCEL_CONCERN);
454 | attentionSetting.setVisibility(View.VISIBLE);
455 | privatelySetting.setVisibility(View.GONE);
456 | //速度显示
457 | attentionSpeedTv.setText("(" + Config.getInstance(this).getAttentionSpeed() / 1000 + "~" + (Config.getInstance(this).getAttentionSpeed() / 1000 + 2) + "秒/个)");
458 | attentionSpeedSb.setProgress((int) (Config.getInstance(this).getAttentionSpeed() / 1000));
459 | privatelySpeedTv.setText("(" + Config.getInstance(this).getPrivatelySpeed() / 1000 + "~" + (Config.getInstance(this).getPrivatelySpeed() / 1000 + 2) + "秒/个)");
460 | privatelySpeedSb.setProgress((int) (Config.getInstance(this).getPrivatelySpeed() / 1000));
461 | }
462 | if (i == 2) {
463 | Config.getInstance(this).setOption(Config.PRIVATELY);
464 | attentionSetting.setVisibility(View.GONE);
465 | privatelySetting.setVisibility(View.VISIBLE);
466 | //私信内容显示
467 | privatelyContent.setText(Config.getInstance(this).getPrivatelyContentText());
468 | }
469 | if (i == 3) {
470 | Config.getInstance(this).setOption(Config.PRIVATELY);
471 | attentionSetting.setVisibility(View.GONE);
472 | privatelySetting.setVisibility(View.VISIBLE);
473 | //私信内容显示
474 | privatelyContent.setText(Config.getInstance(this).getPrivatelyContentText());
475 | }
476 | if (i == 4) {
477 | Config.getInstance(this).setOption(Config.PRIVATELY);
478 | attentionSetting.setVisibility(View.GONE);
479 | privatelySetting.setVisibility(View.VISIBLE);
480 | //私信内容显示
481 | privatelyContent.setText(Config.getInstance(this).getPrivatelyContentText());
482 | }
483 | if (i == 5) {
484 | Config.getInstance(this).setOption(Config.PRIVATELY);
485 | attentionSetting.setVisibility(View.GONE);
486 | privatelySetting.setVisibility(View.VISIBLE);
487 | //私信内容显示
488 | privatelyContent.setText(Config.getInstance(this).getPrivatelyContentText());
489 | }
490 | // if (i == 6) {
491 | // Config.getInstance(this).setOption(Config.COMMENT_PRIVATELY);
492 | // attentionSetting.setVisibility(View.GONE);
493 | // privatelySetting.setVisibility(View.VISIBLE);
494 | // privatelyContent.setText(Config.getInstance(this).getPrivatelyContentText());
495 | // }
496 | }
497 | if (adapterView.getId() == R.id.tiktok_version_spinner) {
498 | Map viewIdMap = new HashMap<>();
499 | for (ViewId viewId : Config.getInstance(getApplicationContext()).getViewIds()) {
500 | //筛选版本
501 | if (versionList.get(i).equals(viewId.getVersion())) {
502 | viewIdMap.put(viewId.getClickInfo(), viewId.getViewId());
503 | }
504 | }
505 | Config.getInstance(getApplicationContext()).setViewIdByVersionMap(viewIdMap);
506 | }
507 |
508 | }
509 |
510 | @Override
511 | public void onNothingSelected(AdapterView> adapterView) {
512 |
513 | }
514 | }
515 |
--------------------------------------------------------------------------------