CJ 1 gadu atpakaļ
vecāks
revīzija
9357ae8815
100 mainītis faili ar 6415 papildinājumiem un 0 dzēšanām
  1. 14 0
      dtok-app/.gitignore
  2. 3 0
      dtok-app/.idea/.gitignore
  3. 116 0
      dtok-app/.idea/codeStyles/Project.xml
  4. 6 0
      dtok-app/.idea/compiler.xml
  5. 23 0
      dtok-app/.idea/deploymentTargetDropDown.xml
  6. 6 0
      dtok-app/.idea/encodings.xml
  7. 22 0
      dtok-app/.idea/gradle.xml
  8. 8 0
      dtok-app/.idea/inspectionProfiles/Project_Default.xml
  9. 60 0
      dtok-app/.idea/jarRepositories.xml
  10. 6 0
      dtok-app/.idea/kotlinc.xml
  11. 10 0
      dtok-app/.idea/migrations.xml
  12. 15 0
      dtok-app/.idea/misc.xml
  13. 6 0
      dtok-app/.idea/vcs.xml
  14. 2 0
      dtok-app/README.md
  15. 1 0
      dtok-app/app/.gitignore
  16. 139 0
      dtok-app/app/build.gradle
  17. BIN
      dtok-app/app/libs/activity-1.8.0.aar
  18. BIN
      dtok-app/app/libs/emulatorview-release.aar
  19. BIN
      dtok-app/app/libs/libtermexec-release.aar
  20. BIN
      dtok-app/app/libs/opencv-3.4.3.aar
  21. BIN
      dtok-app/app/libs/term-debug.aar
  22. 21 0
      dtok-app/app/proguard-rules.pro
  23. BIN
      dtok-app/app/release/app-arm64-v8a-release.apk
  24. BIN
      dtok-app/app/release/app-armeabi-v7a-release.apk
  25. BIN
      dtok-app/app/release/app-x86-release.apk
  26. 47 0
      dtok-app/app/release/output-metadata.json
  27. 26 0
      dtok-app/app/src/androidTest/java/com/cj/autojs/dtok/ExampleInstrumentedTest.java
  28. 99 0
      dtok-app/app/src/main/AndroidManifest.xml
  29. BIN
      dtok-app/app/src/main/assets/project/auto.js.png
  30. 1530 0
      dtok-app/app/src/main/assets/project/main.js
  31. 13 0
      dtok-app/app/src/main/assets/project/project.json
  32. 167 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/Api.java
  33. 79 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/App.kt
  34. 38 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/BaseActivity.java
  35. 50 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/DrawOverlaysPermission.java
  36. 203 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/LoginActivity.java
  37. 216 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/MainActivity.java
  38. 50 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/Pref.kt
  39. 91 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/SplashActivity.java
  40. 53 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/AccessibilityServiceTool.kt
  41. 105 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/DemoAutoJs.kt
  42. 95 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/GlobalKeyObserver.kt
  43. 37 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/ScriptExecutionGlobalListener.kt
  44. 42 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/XJavaScriptEngine.kt
  45. 16 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/config/UrlConfig.java
  46. 108 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/entity/Device.java
  47. 87 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/entity/User.java
  48. 289 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularActionMenu.java
  49. 137 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularMenu.java
  50. 13 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularMenuFloaty.java
  51. 231 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularMenuWindow.java
  52. 82 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/FloatyWindowManger.java
  53. 43 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/OrientationAwareWindowBridge.java
  54. 56 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/gesture/BounceDragGesture.java
  55. 140 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/gesture/DragGesture.java
  56. 342 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/jsinterface/JsInterface.java
  57. 157 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/launch/AssetsProjectLauncher.kt
  58. 11 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/launch/GlobalProjectLauncher.kt
  59. 92 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/service/ForegroundService.java
  60. 491 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/util/DeviceUtil.java
  61. 47 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/util/DrawOverlaysPermission.java
  62. 6 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/util/NoticePermissionUtil.java
  63. 243 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/util/PermissionsSettingsUtil.java
  64. 275 0
      dtok-app/app/src/main/java/com/cj/autojs/dtok/util/SharedPreferencesUtils.java
  65. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libjackpal-androidterm5.so
  66. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libjackpal-termexec2.so
  67. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libjpgt.so
  68. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/liblept.so
  69. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libopencv_java4.so
  70. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libp7zip.so
  71. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libpngt.so
  72. BIN
      dtok-app/app/src/main/jniLibs/arm64-v8a/libtess.so
  73. BIN
      dtok-app/app/src/main/jniLibs/armeabi-v7a/libjackpal-androidterm5.so
  74. BIN
      dtok-app/app/src/main/jniLibs/armeabi-v7a/libjackpal-termexec2.so
  75. BIN
      dtok-app/app/src/main/jniLibs/armeabi-v7a/libopencv_java3.so
  76. BIN
      dtok-app/app/src/main/jniLibs/armeabi/libjackpal-androidterm5.so
  77. BIN
      dtok-app/app/src/main/jniLibs/armeabi/libjackpal-termexec2.so
  78. 6 0
      dtok-app/app/src/main/res/color/abc_background_cache_hint_selector_material_dark.xml
  79. 6 0
      dtok-app/app/src/main/res/color/abc_background_cache_hint_selector_material_light.xml
  80. 6 0
      dtok-app/app/src/main/res/color/abc_btn_colored_borderless_text_material.xml
  81. 6 0
      dtok-app/app/src/main/res/color/abc_btn_colored_text_material.xml
  82. 6 0
      dtok-app/app/src/main/res/color/abc_hint_foreground_material_dark.xml
  83. 6 0
      dtok-app/app/src/main/res/color/abc_hint_foreground_material_light.xml
  84. 6 0
      dtok-app/app/src/main/res/color/abc_primary_text_disable_only_material_dark.xml
  85. 6 0
      dtok-app/app/src/main/res/color/abc_primary_text_disable_only_material_light.xml
  86. 6 0
      dtok-app/app/src/main/res/color/abc_primary_text_material_dark.xml
  87. 6 0
      dtok-app/app/src/main/res/color/abc_primary_text_material_light.xml
  88. 7 0
      dtok-app/app/src/main/res/color/abc_search_url_text.xml
  89. 6 0
      dtok-app/app/src/main/res/color/abc_secondary_text_material_dark.xml
  90. 6 0
      dtok-app/app/src/main/res/color/abc_secondary_text_material_light.xml
  91. 7 0
      dtok-app/app/src/main/res/color/abc_tint_btn_checkable.xml
  92. 11 0
      dtok-app/app/src/main/res/color/abc_tint_default.xml
  93. 7 0
      dtok-app/app/src/main/res/color/abc_tint_edittext.xml
  94. 6 0
      dtok-app/app/src/main/res/color/abc_tint_seek_thumb.xml
  95. 7 0
      dtok-app/app/src/main/res/color/abc_tint_spinner.xml
  96. 7 0
      dtok-app/app/src/main/res/color/abc_tint_switch_track.xml
  97. 6 0
      dtok-app/app/src/main/res/color/app_dialog_button_color_selector.xml
  98. 6 0
      dtok-app/app/src/main/res/color/checkbox_themeable_attribute_color.xml
  99. 8 0
      dtok-app/app/src/main/res/color/design_box_stroke_color.xml
  100. 6 0
      dtok-app/app/src/main/res/color/design_error.xml

+ 14 - 0
dtok-app/.gitignore

@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx

+ 3 - 0
dtok-app/.idea/.gitignore

@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml

+ 116 - 0
dtok-app/.idea/codeStyles/Project.xml

@@ -0,0 +1,116 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <codeStyleSettings language="XML">
+      <indentOptions>
+        <option name="CONTINUATION_INDENT_SIZE" value="4" />
+      </indentOptions>
+      <arrangement>
+        <rules>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:android</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:id</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>style</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>ANDROID_ATTRIBUTE_ORDER</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>.*</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+        </rules>
+      </arrangement>
+    </codeStyleSettings>
+  </code_scheme>
+</component>

+ 6 - 0
dtok-app/.idea/compiler.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <bytecodeTargetLevel target="1.8" />
+  </component>
+</project>

+ 23 - 0
dtok-app/.idea/deploymentTargetDropDown.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="deploymentTargetDropDown">
+    <value>
+      <entry key="app">
+        <State>
+          <runningDeviceTargetSelectedWithDropDown>
+            <Target>
+              <type value="RUNNING_DEVICE_TARGET" />
+              <deviceKey>
+                <Key>
+                  <type value="SERIAL_NUMBER" />
+                  <value value="adb-1479d82-B2KSV1._adb-tls-connect._tcp" />
+                </Key>
+              </deviceKey>
+            </Target>
+          </runningDeviceTargetSelectedWithDropDown>
+          <timeTargetWasSelectedWithDropDown value="2024-03-16T16:33:52.895989800Z" />
+        </State>
+      </entry>
+    </value>
+  </component>
+</project>

+ 6 - 0
dtok-app/.idea/encodings.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
+    <file url="PROJECT" charset="UTF-8" />
+  </component>
+</project>

+ 22 - 0
dtok-app/.idea/gradle.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleMigrationSettings" migrationVersion="1" />
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleJvm" value="corretto-1.8" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/autojs" />
+            <option value="$PROJECT_DIR$/automator" />
+            <option value="$PROJECT_DIR$/common" />
+          </set>
+        </option>
+        <option name="resolveExternalAnnotations" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 8 - 0
dtok-app/.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,8 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,okhttp3.Call,execute" />
+    </inspection_tool>
+  </profile>
+</component>

+ 60 - 0
dtok-app/.idea/jarRepositories.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="BintrayJCenter" />
+      <option name="name" value="BintrayJCenter" />
+      <option name="url" value="https://jcenter.bintray.com/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="Google" />
+      <option name="name" value="Google" />
+      <option name="url" value="https://dl.google.com/dl/android/maven2/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven4" />
+      <option name="name" value="maven4" />
+      <option name="url" value="https://oss.sonatype.org/content/repositories/snapshots/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven3" />
+      <option name="name" value="maven3" />
+      <option name="url" value="https://jitpack.io" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven" />
+      <option name="name" value="maven" />
+      <option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven2" />
+      <option name="name" value="maven2" />
+      <option name="url" value="http://maven.aliyun.com/nexus/content/repositories/jcenter" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="E:\Android\android-sdk\extras\google\m2repository" />
+      <option name="name" value="E:\Android\android-sdk\extras\google\m2repository" />
+      <option name="url" value="file:/E:/Android/android-sdk/extras/google/m2repository" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="E:\Android\android-sdk\extras\android\m2repository" />
+      <option name="name" value="E:\Android\android-sdk\extras\android\m2repository" />
+      <option name="url" value="file:/E:/Android/android-sdk/extras/android/m2repository" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="E:\Android\android-sdk\extras\m2repository" />
+      <option name="name" value="E:\Android\android-sdk\extras\m2repository" />
+      <option name="url" value="file:/E:/Android/android-sdk/extras/m2repository" />
+    </remote-repository>
+  </component>
+</project>

+ 6 - 0
dtok-app/.idea/kotlinc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="KotlinJpsPluginSettings">
+    <option name="version" value="1.6.21" />
+  </component>
+</project>

+ 10 - 0
dtok-app/.idea/migrations.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectMigrations">
+    <option name="MigrateToGradleLocalJavaHome">
+      <set>
+        <option value="$PROJECT_DIR$" />
+      </set>
+    </option>
+  </component>
+</project>

+ 15 - 0
dtok-app/.idea/misc.xml

@@ -0,0 +1,15 @@
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="corretto-1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+  <component name="VisualizationToolProject">
+    <option name="state">
+      <ProjectState>
+        <option name="scale" value="0.2387140902872777" />
+      </ProjectState>
+    </option>
+  </component>
+</project>

+ 6 - 0
dtok-app/.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>

+ 2 - 0
dtok-app/README.md

@@ -0,0 +1,2 @@
+# autojsdemo
+一个可以直接运行autojs脚本的app

+ 1 - 0
dtok-app/app/.gitignore

@@ -0,0 +1 @@
+/build

+ 139 - 0
dtok-app/app/build.gradle

@@ -0,0 +1,139 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'com.jakewharton.butterknife'
+
+android {
+    compileSdkVersion 29
+    buildToolsVersion "29.0.3"
+
+    defaultConfig {
+        applicationId "com.cj.autojs.dtok"
+        minSdkVersion 21
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+        buildConfigField "String", "AGENT_USER_ID", "\"1\""
+        buildConfigField "String", "PRODUCT_NAME","\"dtok\""
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    lintOptions {
+        abortOnError false
+        disable 'MissingTranslation'
+        disable 'ExtraTranslation'
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+    splits {
+        // Configures multiple APKs based on ABI.
+        abi {
+            // Enables building multiple APKs per ABI.
+            enable true
+                // By default all ABIs are included, so use reset() and include to specify that we only
+                // want APKs for x86 and x86_64.
+                // Resets the list of ABIs that Gradle should create APKs for to none.
+            reset()
+            // Specifies a list of ABIs that Gradle should create APKs for.
+            include "x86", "armeabi-v7a","arm64-v8a"
+            // Specifies that we do not want to also generate a universal APK that includes all ABIs.
+            universalApk false
+        }
+        buildTypes {
+            release {
+                minifyEnabled false
+                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+            }
+        }
+    }
+}
+
+def buildApkPluginForAbi(File pluginProjectDir, String abi) {
+    copy {
+        from file('..\\app\\release\\')
+        into new File(pluginProjectDir, 'app\\src\\main\\assets')
+        def fileName = "inrt-" + abi + "-release.apk"
+        include fileName
+        rename fileName, 'template.apk'
+    }
+    exec {
+        workingDir pluginProjectDir
+        commandLine 'gradlew.bat', 'assembleRelease'
+    }
+    copy {
+        from new File(pluginProjectDir, 'app\\build\\outputs\\apk\\release')
+        into file('..\\common\\release')
+        def fileName = '打包插件-' + versions.appVersionName + '-release.apk'
+        include fileName
+        rename fileName, '打包插件-' + abi + '-' + versions.appVersionName + '-release.apk'
+    }
+}
+
+task buildApkPlugin {
+    doLast {
+        def pluginProjectDirPath = '..\\..\\AutoJsApkBuilderPlugin'
+        def pluginProjectDir = file(pluginProjectDirPath)
+        if (!pluginProjectDir.exists() || !pluginProjectDir.isDirectory()) {
+            println 'pluginProjectDir not exists'
+            return
+        }
+        buildApkPluginForAbi(pluginProjectDir, 'armeabi-v7a')
+        buildApkPluginForAbi(pluginProjectDir, 'x86')
+        buildApkPluginForAbi(pluginProjectDir, 'arm64-v8a')
+    }
+}
+
+tasks.whenTaskAdded { task ->
+    if (task.name == 'assembleRelease') {
+        task.finalizedBy 'buildApkPlugin'
+    }
+}
+
+repositories {
+    flatDir {
+        dirs 'libs'
+    }
+    google()
+}
+dependencies {
+
+    implementation 'com.makeramen:roundedimageview:2.3.0'
+//    implementation 'com.github.ZLYang110:MyPermission:1.0'
+
+
+    implementation fileTree(dir: "libs", include: ["*.jar"])
+    //Glide
+    implementation('com.github.bumptech.glide:glide:4.2.0', {
+        exclude group: 'com.android.support'
+    })
+    implementation ('com.github.lzyzsd:jsbridge:2.0.0'){
+        exclude group: 'com.github.lzyzsd.jsbridge', module: 'jsbridge-debug'
+    }
+
+    implementation('com.jakewharton:butterknife:10.2.1', {
+        exclude group: 'com.android.support'
+    })
+    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
+
+
+    implementation 'androidx.appcompat:appcompat:1.1.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+    implementation 'com.google.android.material:material:1.5.0-alpha02'
+//    implementation 'androidx.activity:activity:1.8.0'
+//    implementation 'com.google.android.material:material:1.11.0'
+//    implementation files('libs/activity-1.7.2.aar')
+    implementation "androidx.activity:activity:1.2.4"
+    implementation 'com.blankj:utilcodex:1.31.1'
+
+//    implementation 'com.google.android.material:material:1.11.0'
+//    implementation 'androidx.activity:activity:1.8.0'
+        testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+    androidTestImplementation "android.arch.core:core-testing:1.1.0"
+
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+    implementation project(':autojs')
+    implementation 'com.yanzhenjie:permission:2.0.3'
+}

BIN
dtok-app/app/libs/activity-1.8.0.aar


BIN
dtok-app/app/libs/emulatorview-release.aar


BIN
dtok-app/app/libs/libtermexec-release.aar


BIN
dtok-app/app/libs/opencv-3.4.3.aar


BIN
dtok-app/app/libs/term-debug.aar


+ 21 - 0
dtok-app/app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

BIN
dtok-app/app/release/app-arm64-v8a-release.apk


BIN
dtok-app/app/release/app-armeabi-v7a-release.apk


BIN
dtok-app/app/release/app-x86-release.apk


+ 47 - 0
dtok-app/app/release/output-metadata.json

@@ -0,0 +1,47 @@
+{
+  "version": 2,
+  "artifactType": {
+    "type": "APK",
+    "kind": "Directory"
+  },
+  "applicationId": "com.cj.autojs.dtok",
+  "variantName": "release",
+  "elements": [
+    {
+      "type": "ONE_OF_MANY",
+      "filters": [
+        {
+          "filterType": "ABI",
+          "value": "x86"
+        }
+      ],
+      "versionCode": 1,
+      "versionName": "1.0",
+      "outputFile": "app-x86-release.apk"
+    },
+    {
+      "type": "ONE_OF_MANY",
+      "filters": [
+        {
+          "filterType": "ABI",
+          "value": "armeabi-v7a"
+        }
+      ],
+      "versionCode": 1,
+      "versionName": "1.0",
+      "outputFile": "app-armeabi-v7a-release.apk"
+    },
+    {
+      "type": "ONE_OF_MANY",
+      "filters": [
+        {
+          "filterType": "ABI",
+          "value": "arm64-v8a"
+        }
+      ],
+      "versionCode": 1,
+      "versionName": "1.0",
+      "outputFile": "app-arm64-v8a-release.apk"
+    }
+  ]
+}

+ 26 - 0
dtok-app/app/src/androidTest/java/com/cj/autojs/dtok/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.cj.autojs.dtok;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.yuqiaotech.autojs.demo", appContext.getPackageName());
+    }
+}

+ 99 - 0
dtok-app/app/src/main/AndroidManifest.xml

@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.cj.autojs.dtok">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
+
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.TELEPHONY_SERVICE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.PERMISSION_GRANTED" />
+    <uses-permission
+        android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
+        tools:ignore="ProtectedPermissions" />
+    <uses-permission
+        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+        tools:ignore="ScopedStorage" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
+    <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 非Auto.js运行必需,不会主动申请,某些脚本可以自行申请 -->
+    <uses-permission
+        android:name="android.permission.ACCESS_FINE_LOCATION"
+        tools:ignore="CoarseFineLocation" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+
+    <application
+        android:name="com.cj.autojs.dtok.App"
+        android:allowBackup="true"
+        android:icon="@drawable/logo"
+        android:label="@string/app_name"
+        android:networkSecurityConfig="@xml/network_security_config"
+        android:roundIcon="@drawable/logo"
+        android:theme="@style/AppTheme"
+        android:usesCleartextTraffic="true"
+        tools:ignore="GoogleAppIndexingWarning"
+        tools:replace="android:label, android:allowBackup"
+        tools:targetApi="m">
+        <activity
+            android:name="com.cj.autojs.dtok.MainActivity"
+            android:exported="false" />
+        <activity
+            android:name="com.cj.autojs.dtok.SplashActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="com.cj.autojs.dtok.LoginActivity"
+            android:exported="false"
+            android:launchMode="singleTask" />
+
+        <service
+            android:name="com.stardust.notification.NotificationListenerService"
+            android:exported="true"
+            android:label="inrt"
+            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.notification.NotificationListenerService" />
+            </intent-filter>
+        </service>
+        <service
+            android:name="com.stardust.view.accessibility.AccessibilityService"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/accessibility_service_config" />
+        </service>
+        <service
+            android:name="com.cj.autojs.dtok.service.ForegroundService"
+            android:exported="false"
+            android:foregroundServiceType="mediaProjection" />
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="com.cj.autojs.dtok"
+            android:exported="false"
+            android:grantUriPermissions="true">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_paths" />
+        </provider>
+    </application>
+
+</manifest>

BIN
dtok-app/app/src/main/assets/project/auto.js.png


+ 1530 - 0
dtok-app/app/src/main/assets/project/main.js

@@ -0,0 +1,1530 @@
+ launch('com.ss.android.ugc.aweme');
+ (() => {
+        var __webpack_modules__ = {
+            81: (module, __unused_webpack_exports, __webpack_require__) => {
+                __webpack_require__ = {
+                    packageName: "com.ss.android.ugc.aweme",
+                                   versions: [ "26.0.0", "27.0.0", "28.0.0", "28.1.0", "28.2.0", "28.3.0", "28.4.0", "28.5.0", "28.6.0", "28.7.0", "28.8.0", "28.9.0", "29.0.0" ,"29.1.0"],
+
+                    nodes: __webpack_require__(761),
+                    commonts: [ "又刷到你了", "看看我的作品", "来我主页转转" ],
+                    sxhs: [ "很高兴认识你", "常来常往" ],
+                    zfhs: [ "互粉", "回关", "关注", "互赞" ],
+                    czyhGjzs: [ "多少", "价格", "联系" ],
+                    dqGjzs: [ "安徽", "浙江", "江苏" ]
+                };
+                module.exports = __webpack_require__;
+            },
+            761: module => {
+                var nodes = {
+                    all: {
+                        index: {
+                            headimg: {
+                                id: "com.ss.android.ugc.aweme:id/user_avatar"
+                            },
+                            desc: {
+                                id: "com.ss.android.ugc.aweme:id/desc"
+                            },
+                            title: {
+                                id: "com.ss.android.ugc.aweme:id/title"
+                            },
+                            searchInput: {
+                                id: "com.ss.android.ugc.aweme:id/et_search_kw"
+                            }
+                        }
+                    },
+                    "26.0.0": {
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dc7"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/er2"
+                            }
+                        },
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/er-"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/t5o"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/w8o"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/w8s"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/nsc"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/w9h"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/po9"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/mwq"
+                            },
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/xzb"
+                            }
+                        }
+                    },
+                    "27.0.0": {
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dh7"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/eyg"
+                            }
+                        },
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/eyp"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/vkl"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/yr5"
+                            },
+                         fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/yr9"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/ohq"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/ys7"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/qpd"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/njx"
+                            },
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/zkc"
+                            }
+                        }
+                    },
+                    "27.3.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/e3z"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dms"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/e3p"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v0f"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/y=3"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/y=7"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/oth"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/y_7"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q1y"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nu1"
+                            },
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z35"
+                            }
+                        }
+                    },
+                    "27.4.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/e3="
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dm2"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/e30"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v0u"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/y_h"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/y_l"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/os-"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/y-k"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q19"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nuw"
+                            },
+                         userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z4t"
+                            }
+                        }
+                    },
+                    "27.5.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/e3+"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dnm"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/e33"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v1f"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/y-e"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/y-i"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/osz"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/y+h"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q2n"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nuh"
+                            },
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z5o"
+                            }
+                        }
+                    },
+                    "27.6.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/e5o"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dow"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/e5e"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v2+"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/y+-"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zac"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/ouo"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/za+"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q4b"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nv8"
+                            },
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z7s"
+                            }
+                        }
+                    },
+                    "27.7.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/exn"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/df+"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/exd"
+                            }
+                        },
+                        user: {
+                         homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v83"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zic"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zig"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/ov4"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zjf"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q6o"
+                            }
+                        },
+                        live: {
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nsz"
+                            },
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0cc"
+                            }
+                        }
+                    },
+                    "27.8.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/eyq"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dg_"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/eyg"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v_e"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zku"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zky"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/oyz"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zlu"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q72"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0ew"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nwv"
+                            }
+                        }
+                    },
+                    "27.9.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ezh"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dhs"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ey="
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/waf"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zn6"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zn="
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/o0p"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zo7"
+                            },
+                            followBtn: {
+                             id: "com.ss.android.ugc.aweme:id/q97"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0h="
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nz9"
+                            }
+                        }
+                    },
+                    "28.0.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ezh"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dho"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ey="
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/wcy"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zqq"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zqu"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/o13"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zrr"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q_r"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0kz"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/n19"
+                            }
+                        }
+                    },
+                    "28.1.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ezy"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/dh0"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ezo"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/wd8"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zrs"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zrw"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/o2_"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zsu"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q-1"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0lw"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/n3u"
+                            }
+                        }
+                    },
+                    "28.2.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/efs"
+                            }
+                        },
+                        comment: {
+                            button: {
+                             id: "com.ss.android.ugc.aweme:id/c1a"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/efi"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/vsx"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/y6j"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/y6n"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/oe9"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/y7f"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/qod"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/zzu"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nbk"
+                            }
+                        }
+                    },
+                    "28.3.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/egc"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c1r"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ef6"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/vvo"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/y9g"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/y9k"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/og0"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/y=c"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/qp-"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z2s"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nc4"
+                            }
+                        }
+                    },
+                    "28.4.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ehq"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c2="
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ehf"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v09"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zbf"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zbj"
+                            },
+                            username: {
+                             id: "com.ss.android.ugc.aweme:id/old"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zcb"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/qu-"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z9i"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/ng7"
+                            }
+                        }
+                    },
+                    "28.5.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/eio"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c31"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/eid"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v3+"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zex"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/ze1"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/on1"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zft"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/qx3"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/z-5"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nje"
+                            }
+                        }
+                    },
+                    "28.6.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ei-"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c4g"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ei1"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v7c"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zh="
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zia"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/op1"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zi7"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/qz9"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0ck"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nk-"
+                            }
+                        }
+                    },
+                 "28.7.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ejz"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c41"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ejo"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v97"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zk="
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zla"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/ory"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zl6"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q2d"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0fr"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nm6"
+                            }
+                        }
+                    },
+                    "28.8.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/ekj"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c5g"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/ej-"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/v+_"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zph"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zpl"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/ot-"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zqd"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q47"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0jz"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nor"
+                            }
+                        }
+                    },
+                    "28.9.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/el2"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c6w"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/elr"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/wej"
+                            },
+                            gznum: {
+                             id: "com.ss.android.ugc.aweme:id/zt8"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zt-"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/owx"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zu4"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q7="
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0ol"
+                            },
+  msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nrb"
+                            }
+                        }
+                    },
+                    "29.0.0": {
+                        video: {
+                            like: {
+                                id: "com.ss.android.ugc.aweme:id/el5"
+                            }
+                        },
+                        comment: {
+                            button: {
+                                id: "com.ss.android.ugc.aweme:id/c6v"
+                            },
+                            zan: {
+                                id: "com.ss.android.ugc.aweme:id/elu"
+                            }
+                        },
+                        user: {
+                            homeMark: {
+                                id: "com.ss.android.ugc.aweme:id/wgx"
+                            },
+                            gznum: {
+                                id: "com.ss.android.ugc.aweme:id/zxf"
+                            },
+                            fansnum: {
+                                id: "com.ss.android.ugc.aweme:id/zxj"
+                            },
+                            username: {
+                                id: "com.ss.android.ugc.aweme:id/ox2"
+                            },
+                            lanv: {
+                                id: "com.ss.android.ugc.aweme:id/zyb"
+                            },
+                            followBtn: {
+                                id: "com.ss.android.ugc.aweme:id/q9u"
+                            }
+                        },
+                        live: {
+                            userlistbox: {
+                                id: "com.ss.android.ugc.aweme:id/0r0"
+                            },
+                            msglistbox: {
+                                id: "com.ss.android.ugc.aweme:id/nrq"
+                            }
+                        }
+                    },
+                      "29.1.0": {
+                                            video: {
+                                                like: {
+                                                    id: "com.ss.android.ugc.aweme:id/emy"
+                                                }
+                                            },
+                                            comment: {
+                                                button: {
+                                                    id: "com.ss.android.ugc.aweme:id/c7i"
+                                                },
+                                                zan: {
+                                                    id: "com.ss.android.ugc.aweme:id/eml"
+                                                }
+                                            },
+                                            user: {
+                                                homeMark: {
+                                                    id: "com.ss.android.ugc.aweme:id/poo"
+                                                },
+                                                gznum: {
+                                                    id: "com.ss.android.ugc.aweme:id/z1u"
+                                                },
+                                                fansnum: {
+                                                    id: "com.ss.android.ugc.aweme:id/z1y"
+                                                },
+                                                username: {
+                                                    id: "com.ss.android.ugc.aweme:id/o07"
+                                                },
+                                                lanv: {
+                                                    id: "com.ss.android.ugc.aweme:id/z2q"
+                                                },
+                                                followBtn: {
+                                                    id: "com.ss.android.ugc.aweme:id/q-z"
+                                                }
+                                            },
+                                            live: {
+                                                userlistbox: {
+                                                    id: "com.ss.android.ugc.aweme:id/0wc"
+                                                },
+                                                msglistbox: {
+                                                    id: "com.ss.android.ugc.aweme:id/nv_"
+                                                }
+                                            }
+                                        }
+                };
+                module.exports = nodes;
+            },
+            954: (module, __unused_webpack_exports, __webpack_require__) => {
+                var conf = __webpack_require__(81), utility = __webpack_require__(871), engine = __webpack_require__(557), douyin = {
+                    version: "",
+                    nodes: {},
+                    init() {
+                        var info = utility.packageInfo(conf.packageName);
+                        return utility.isEmpty(info) ? (alert("请安装支持的抖音版本!"), !1) : conf.versions.includes(info.versionName) ? (this.version = info.versionName,
+                        this.nodes = conf.nodes[info.versionName] || {}, !0) : (alert("不支持 抖音(" + info.versionName + ")请安装支持的抖音版本!"),
+                        !1);
+                    },
+                    execClose() {
+                        for (utility.inputHide(); ;) {
+                            var closeBtn = desc("关闭").visibleToUser().findOnce();
+                            if (!closeBtn) break;
+                            closeBtn.click(), sleep(1e3);
+                        }
+                    },
+                    execCancel() {
+                        for (;;) {
+                            var closeBtn = id("cancel_btn").visibleToUser().findOnce();
+                            if (!closeBtn) break;
+                            closeBtn.click(), sleep(1e3);
+                        }
+                    },
+                    execBackOnce() {
+                        var backBtn = desc("返回").visibleToUser().findOnce();
+                        return null !== backBtn && (backBtn.click(), sleep(500), !0);
+                    },
+                    execBack() {
+                        for (;this.execBackOnce(); );
+                    },
+                    execLike() {
+                        var wdz = className("android.widget.LinearLayout").descStartsWith("未点赞").descEndsWith("按钮").visibleToUser().findOnce();
+                        return !!wdz && (utility.toast("执行点赞"), wdz.click(), sleep(1e3),
+                        !0);
+                    },
+                    execTxdz() {
+                        var txdz;
+                        desc("用户头像").visibleToUser().findOnce().click() && (sleep(500),
+                        txdz = className("android.widget.RelativeLayout").visibleToUser().findOnce(),
+                        sleep(500), txdz.click(), engine.sleepMs(1e3, 2e3), back(),
+                        sleep(1e3));
+                    },
+                    popupAndClose() {
+                        threads.start(function() {
+                            for (;;) {
+                                var a;
+                                sleep(200), text("授权提示").exists() && text("同意授权").click(),
+                                sleep(200), text("休息一下吧").exists() && text("取消").click(),
+                                sleep(200), (text("很晚了,睡个好觉").exists() || text("早点睡觉吧").exists()) && text("取消").click(),
+                                sleep(200), text("朋友推荐").exists() && (a = desc("关闭").findOnce()) && a.click(),
+                             sleep(200), text("发现通讯录好友").exists() && text("取消").click(),
+                                sleep(200), text("个人信息保护指引").exists() && text("好的").click(),
+                                sleep(200), text("去商店评分").exists() && text("取消").click(),
+                                sleep(200), text("开启青少年模式").exists() && text("我知道了").click(),
+                                sleep(200), text("检测到更新").exists() && text("以后再说").click(),
+                                sleep(200), text("跳过广告").exists() && text("跳过广告").click(),
+                                sleep(200), text("下次").exists() && text("下次").click(),
+                                sleep(1e3);
+                            }
+                        });
+                    },
+                    getNode(path) {
+                        var tp, path = path.split(".");
+                        let node = this.nodes;
+                        for (tp of path) if (null === (node = node[tp] || null)) break;
+                        if (!node) {
+                            node = conf.nodes.all;
+                            for (let tp of path) if (null === (node = node[tp] || null)) break;
+                        }
+                        return node;
+                    },
+                    isRecommend() {
+                        return null !== descContains("推荐").descEndsWith("按钮").descContains("已选中").visibleToUser().findOnce() || null !== descContains("精选").descEndsWith("按钮").descContains("已选中").visibleToUser().findOnce();
+                    },
+                    IsVideo() {
+                        var node = douyin.getNode("video.like");
+                        return null !== node && null !== id(node.id).visibleToUser().findOnce() || null !== className("android.widget.LinearLayout").descContains("点赞").descEndsWith("按钮").visibleToUser().findOnce();
+                    },
+                    IsVideoDelay(ms) {
+                        return null !== className("android.widget.LinearLayout").descContains("点赞").descEndsWith("按钮").visibleToUser().findOne(ms);
+                    },
+                    skipVideo() {
+                        return !this.IsVideo() && (utility.toast("跳过非视频或图集作品!"), sleep(500),
+                        engine.slide(), !0);
+                    },
+                    IsFollow() {
+                        return null !== className("android.widget.Button").desc("关注").visibleToUser().findOnce();
+                    },
+                    execFollow() {
+                        var con = className("android.widget.Button").desc("关注").visibleToUser().findOnce();
+                        return !!con && (utility.toast("执行关注"), con.click(), !0);
+                    },
+                    sikpFollow() {
+                        return !this.IsFollow() && (utility.toast("跳过已关注用户"), sleep(500),
+                        engine.slide(), !0);
+                    },
+                    IsLike() {
+                        return null !== className("android.widget.LinearLayout").descStartsWith("已点赞").descEndsWith("按钮").visibleToUser().findOnce();
+                    },
+                    sikpLike() {
+                        return !!this.IsLike() && (utility.toast("跳过已点赞视频"), sleep(500),
+                        engine.slide(), !0);
+                    },
+                    getLikeNum() {
+                        let num = 0;
+                        try {
+                            var desc = className("android.widget.LinearLayout").descContains("点赞").descEndsWith("按钮").visibleToUser().findOnce().desc();
+                            num = parseFloat(desc.match(/[0-9]+(\.[0-9]{0,2})?/g)[0]),
+                            (0 <= desc.indexOf("w") || 0 <= desc.indexOf("万")) && (num *= 1e4);
+                        } catch (e) {
+                            num = 0;
+                        }
+                        return num;
+                    },
+                    IsAd() {
+                        return null !== textContains("广告").visibleToUser().findOnce();
+                    },
+                 sikpAp() {
+                        return !!this.IsAd() && (utility.toast("跳过忽略广告"), sleep(500),
+                        engine.slide(), !0);
+                    },
+                    IsCommerce() {
+                        try {
+                            if (null !== textEndsWith("限时秒杀").visibleToUser().findOnce()) return !0;
+                            if (null !== textEndsWith("优惠团购").visibleToUser().findOnce()) return !0;
+                        } catch (e) {}
+                        return !1;
+                    },
+                    sikpCommerce() {
+                        return !!this.IsCommerce() && (utility.toast("跳过商业视频!"), sleep(500),
+                        engine.slide(), !0);
+                    },
+                    watchVideo(startTime, watchTime) {
+                        startTime = engine.getUnix() - startTime;
+                        0 < (watchTime -= startTime = 60 < startTime ? 60 : startTime) ? (engine.sleep(watchTime),
+                        utility.toast("继续观看视频" + watchTime + "秒")) : utility.toast("已观看视频" + startTime + "秒"),
+                        sleep(500);
+                    },
+                    canComment() {
+                        let num = 0;
+                        try {
+                            var desc = className("android.widget.LinearLayout").descContains("评论").descEndsWith("按钮").visibleToUser().findOnce().desc();
+                            num = parseFloat(desc.match(/[0-9]+(\.[0-9]{0,2})?/g)[0]);
+                        } catch (e) {
+                            num = 0;
+                        }
+                        return 0 < num;
+                    },
+                    sendComment(hs, isComment, isLike, pltp) {
+                        try {
+                            isComment = !(!isComment && isComment !== undefined);
+                            var plBtn = className("android.widget.LinearLayout").descStartsWith("评论").descEndsWith("按钮").visibleToUser().findOnce();
+                            if (plBtn && plBtn.click()) {
+                                let editText = className("android.widget.EditText").visibleToUser().findOne(3e3);
+                                if (null === editText && (sleep(1e3), editText = className("android.widget.EditText").visibleToUser().findOne(2e3)),
+                                null === editText) utility.toast("没有识别到评论框"), sleep(500); else {
+                                    isLike && (utility.toast("执行评论点赞"), sleep(1e3),
+                                    (commentZanBtns = descStartsWith("赞").descEndsWith("未选中").visibleToUser().find()).forEach(el => {
+                                        (el.clickable() ? el : el.parent()).click(),
+                                        engine.sleepMs(500, 1e3);
+                                    }));
+                                    var hsLen = hs.length;
+                                    if (!isComment || hsLen < 1) utility.toast("不执行评论"),
+                                    sleep(500); else if (utility.toast("准备发表评论"), editText.click()) {
+                                        if (sleep(1e3), setText(hs[random(0, hsLen - 1)]),
+                                        engine.sleepMs(1e3, 3e3), pltp && null !== desc("插入图片").visibleToUser().findOne(3e3)) {
+                                            desc("插入图片").visibleToUser().findOne().click() || utility.toast("没有成功点击到发布图片按钮"),
+                                            sleep(2e3);
+                                            let listBox = id("com.ss.android.ugc.aweme:id/content_container").visibleToUser().findOne(2e3);
+                                            if (0 == (listBox = listBox.find(id("com.ss.android.ugc.aweme:id/root_view"))).length) return void alert("没有图片!", "手机相册里请先准备好图片!");
+                                            listBox[random(0, listBox.length - 1)].click() || (utility.toast("图片点击失败!"),
+                                            back()), engine.sleepMs(1e3, 2e3);
+                                     }
+                                        let sendBtn = className("android.widget.ImageView").visibleToUser().desc("发送").findOne(5e3);
+                                        if (null === (sendBtn = (sendBtn = sendBtn || className("android.widget.TextView").visibleToUser().text("发送").findOne(5e3)) || text("发送").findOne(5e3))) utility.toast("没有获取到发送按钮"),
+                                        sleep(1e3); else {
+                                            if (sendBtn.clickable()) {
+                                                if (!sendBtn.click()) return utility.toast("没有成功点击发送按钮"),
+                                                sleep(1e3), void this.execClose();
+                                            } else if (!sendBtn.parent().click()) return utility.toast("没有成功点击parent发送按钮"),
+                                            sleep(1e3), void this.execClose();
+                                            utility.toast("评论完成"), null !== text("我也发一张").visibleToUser().findOne(5e3) && this.execBack(),
+                                            engine.sleepMs(2e3, 5e3);
+                                        }
+                                    } else utility.toast("没有成功点击评论框"), sleep(500);
+                                }
+                                this.execClose();
+                            }
+                        } catch (e) {
+                            console.log(e), utility.toast("评论操作失败"), sleep(500), this.execClose();
+                        }
+                    },
+                    isHome() {
+                        return null !== id(this.getNode("user.homeMark").id).visibleToUser().findOne(1e4);
+                    },
+                    previewHome() {
+                        var head = id(this.getNode("index.headimg").id).visibleToUser().findOnce();
+                        null !== head && head.click() && (utility.toast("访问用户首页"), this.isHome() ? (engine.sleep(2, 5),
+                        1 == random(1, 3) && (engine.slide(), engine.sleep(2, 5))) : console.log("打开用户首页失败"),
+                        this.execBackOnce());
+                    },
+                    previewHomeTc() {
+                        let yhxb = 0;
+                        var head = id(this.getNode("index.headimg").id).visibleToUser().findOnce();
+                        if (null !== head && head.click()) {
+                            if (utility.toast("访问用户首页"), this.isHome()) return engine.sleepMs(2e3, 3e3),
+                            null !== descStartsWith("男").visibleToUser().findOnce() && (yhxb = 1),
+                            null !== descStartsWith("女").visibleToUser().findOnce() && (yhxb = 2),
+                            this.execBackOnce(), yhxb;
+                            console.log("打开用户首页失败"), this.execBackOnce();
+                        }
+                    },
+                    getVideoDesc() {
+                        var vedioDesc = id(douyin.getNode("index.desc").id).visibleToUser().findOnce();
+                        return null === vedioDesc ? "" : vedioDesc.text();
+                    },
+                    getVideoTitle() {
+                        var vedioTitle = id(douyin.getNode("index.title").id).visibleToUser().findOnce();
+                        return null === vedioTitle ? "" : vedioTitle.text();
+                    },
+                    getVideoMark() {
+                        return this.getVideoDesc() + this.getVideoTitle();
+                    }
+                };
+                module.exports = douyin;
+            },
+            557: (module, __unused_webpack_exports, __webpack_require__) => {
+                "undefined" == typeof __webpack_require__.g.ENV_CONF && (__webpack_require__.g.ENV_CONF = {}),
+                module.exports = {
+                    deviceWidth: ENV_CONF.screenWidth || device.width,
+                    deviceHeight: ENV_CONF.screenHeight || device.height,
+                    exit() {
+                        engines.stopAll(), exit();
+                    },
+                    swipeEx(qx, qy, zx, zy, time) {
+                     for (var xxy = [ time ], point = [], dx0 = {
+                            x: qx,
+                            y: qy
+                        }, dx1 = {
+                            x: random(qx - 100, qx + 100),
+                            y: random(qy, qy + 50)
+                        }, dx2 = {
+                            x: random(zx - 100, zx + 100),
+                            y: random(zy, zy + 50)
+                        }, dx3 = {
+                            x: zx,
+                            y: zy
+                        }, i = 0; i < 4; i++) eval("point.push(dx" + i + ")");
+                        for (let i = 0; i < 1; i += .08) xxyy = [ parseInt(this.bezier_curves(point, i).x), parseInt(this.bezier_curves(point, i).y) ],
+                        xxy.push(xxyy);
+                        gesture.apply(null, xxy);
+                    },
+                    bezier_curves(cp, t) {
+                        return cx = 3 * (cp[1].x - cp[0].x), bx = 3 * (cp[2].x - cp[1].x) - cx,
+                        ax = cp[3].x - cp[0].x - cx - bx, cy = 3 * (cp[1].y - cp[0].y),
+                        by = 3 * (cp[2].y - cp[1].y) - cy, ay = cp[3].y - cp[0].y - cy - by,
+                        tSquared = t * t, tCubed = tSquared * t, (result = {
+                            x: 0,
+                            y: 0
+                        }).x = ax * tCubed + bx * tSquared + cx * t + cp[0].x, result.y = ay * tCubed + by * tSquared + cy * t + cp[0].y,
+                        result;
+                    },
+                    shortSlide() {
+                        this.swipeEx(.5 * this.deviceWidth, .8 * this.deviceHeight, .5 * this.deviceWidth, .8 * this.deviceHeight - 500, 300);
+                    },
+                    middleSlide() {
+                        this.swipeEx(.5 * this.deviceWidth, .8 * this.deviceHeight, .5 * this.deviceWidth, .5 * this.deviceHeight, 300);
+                    },
+                    deSlide() {
+                        this.swipeEx(.5 * this.deviceWidth, .3 * this.deviceHeight, .5 * this.deviceWidth, this.deviceHeight, 300);
+                    },
+                    bshortSlide() {
+                        this.swipeEx(.5 * this.deviceWidth, .8 * this.deviceHeight, .5 * this.deviceWidth, .8 * this.deviceHeight - 500, 300);
+                    },
+                    slide() {
+                        this.swipeEx(.8 * this.deviceWidth, .7 * this.deviceHeight, .8 * this.deviceWidth, 0, random(300, 500));
+                    },
+                    fanslide() {
+                        this.swipeEx(.9 * this.deviceWidth, .5 * this.deviceHeight, .9 * this.deviceWidth, .01 * this.deviceHeight, 500);
+                    },
+                    regionClick(region) {
+                        click(random(region[0], region[0] + region[2]), random(region[1], region[1] + region[3]));
+                    },
+                    boundsClick(bounds) {
+                        var x = .2 * bounds.width(), y = .2 * bounds.height();
+                        bounds.left += x, bounds.right -= x, bounds.top += y, bounds.bottom -= y,
+                        click(random(bounds.left, bounds.right), random(bounds.top, bounds.bottom));
+                    },
+                    sleepMs() {
+                        var argLen = arguments.length;
+                        let min = 0, max = 0;
+                        if (1 == argLen) min = arguments[0], max = arguments[0]; else {
+                            if (!(2 <= argLen)) return;
+                            min = arguments[0], max = arguments[1];
+                        }
+                        min >= max ? sleep(min) : sleep(random(min, max));
+                    },
+                    sleep() {
+                        var argLen = arguments.length;
+                        let min = 0, max = 0;
+                        if (1 == argLen) min = arguments[0], max = arguments[0]; else {
+                            if (!(2 <= argLen)) return;
+                            min = arguments[0], max = arguments[1];
+                        }
+                        min >= max ? sleep(1e3 * min) : sleep(1e3 * random(min, max));
+                    },
+                    getUnix() {
+                        return parseInt(Date.now() / 1e3);
+                    }
+                };
+            },
+         871: (module, __unused_webpack_exports, __webpack_require__) => {
+                __webpack_require__.g.floatyToastWindow === undefined && (__webpack_require__.g.floatyToastWindow = floaty.rawWindow(`
+     <frame gravity="center" w="*">
+         <text
+             id="text" text=""
+             w="wrap_content" h="wrap_content"
+             visibility="invisible"
+             bg="#1989fa" textColor="#ffffff"
+             paddingLeft="10" paddingRight="10" paddingTop="5" paddingBottom="5"
+             />
+     </frame>
+    `), floatyToastWindow.setTouchable(!1), floatyToastWindow.setSize(-1, -2), floatyToastWindow.setPosition(0, .75 * (ENV_CONF.screenHeight || device.height))),
+                module.exports = {
+                    currentRunPackage(packageName) {
+                        return currentPackage() == conf.packageName || (app.launch(conf.packageName),
+                        !1);
+                    },
+                    packageInfo(packageName) {
+                        try {
+                            return context.getPackageManager().getPackageInfo(packageName, 0);
+                        } catch (e) {
+                            return null;
+                        }
+                    },
+                    checkVersion(packageName, versions) {
+                        var info = this.packageInfo(packageName);
+                        return this.isEmpty(info) ? (alert("请安装抖音!"), !1) : (packageName = app.getAppName(packageName),
+                        !!versions.includes(info.versionName) || (alert("不支持 " + packageName + "(" + info.versionName + "),请安装支持版本!"),
+                        !1));
+                    },
+                    isEmpty(value) {
+                        switch (typeof value) {
+                          case "undefined":
+                            return !0;
+
+                          case "string":
+                            if (0 == value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, "").length) return !0;
+                            break;
+
+                          case "boolean":
+                            if (value) break;
+                            return !0;
+
+                          case "number":
+                            if (0 === value || isNaN(value)) return !0;
+                            break;
+
+                          case "object":
+                            if (null !== value && 0 !== value.length) for (var i in value) return !1;
+                            return !0;
+                        }
+                        return !1;
+                    },
+                    checkProbability(value, hdfs) {
+                        var temp = random(1, 99);
+                        return console.log(hdfs + "计算概率:" + temp + (temp < value ? "未超出" : "超出") + value),
+                        temp < value;
+                    },
+                    strFindKeys(s, keys) {
+                        for (w of keys) if (-1 != s.indexOf(w)) return w;
+                        return "";
+                    },
+                    error(packageName, e) {
+                        if (e.fileName) {
+                            packageName = this.packageInfo(packageName);
+                            let versionName = "未知版本";
+                            packageName = "版本号:" + (versionName = packageName && packageName.versionName ? packageName.versionName : versionName) + "\r\n",
+                            packageName = (packageName = (packageName += "错误:" + e.toString() + "\r\n") + ("模块:" + e.fileName.replace(".js", "") + "\r\n")) + ("错误码:" + e.lineNumber + "\r\n") + "====================================\r\n";
+                            files.write("/sdcard/error_bzy.log", packageName);
+                        } else console.log("运行错误:", e.toString());
+                    },
+                    inputShow() {
+                        for (var i = 0; null != auto.windows[i]; i++) if (2 == auto.windows[i].type) return !0;
+                        return !1;
+                    },
+                    inputHide() {
+                        for (;this.inputShow(); ) back(), sleep(1e3);
+                    },
+                    toast(msg) {
+                        ui.run(function() {
+                         console.log(msg), floatyToastWindow.text.setText(msg), floatyToastWindow.text.attr("visibility", "visible");
+                        });
+                    },
+                    toastHide() {
+                        try {
+                            floatyToastWindow.text.attr("visibility", "invisible");
+                        } catch (e) {}
+                    },
+                    objectToStr(obj) {
+                        try {
+                            var str = obj.toString(), index = str.indexOf(";");
+                            return -1 === index ? "" : str.slice(0, index);
+                        } catch (error) {
+                            return "";
+                        }
+                    },
+                    compareVersion(version1, version2) {
+                        var arr1 = version1.split("."), arr2 = version2.split("."), length1 = arr1.length, length2 = arr2.length, minlength = Math.min(length1, length2);
+                        let i = 0;
+                        for (i; i < minlength; i++) {
+                            var a = parseInt(arr1[i]), b = parseInt(arr2[i]);
+                            if (b < a) return 1;
+                            if (a < b) return -1;
+                        }
+                        if (length2 < length1) {
+                            for (let j = i; j < length1; j++) if (0 != parseInt(arr1[j])) return 1;
+                        } else if (length1 < length2) for (let j = i; j < length2; j++) if (0 != parseInt(arr2[j])) return -1;
+                        return 0;
+                    }
+                };
+            }
+        }, __webpack_module_cache__ = {};
+        function __webpack_require__(moduleId) {
+            var cachedModule = __webpack_module_cache__[moduleId];
+            return cachedModule !== undefined || (cachedModule = __webpack_module_cache__[moduleId] = {
+                exports: {}
+            }, __webpack_modules__[moduleId](cachedModule, cachedModule.exports, __webpack_require__)),
+            cachedModule.exports;
+        }
+        (() => {
+            __webpack_require__.g = function() {
+                if ("object" == typeof globalThis) return globalThis;
+                try {
+                    return this || new Function("return this")();
+                } catch (e) {
+                    if ("object" == typeof window) return window;
+                }
+            }();
+        })();
+        var __webpack_exports__ = {};
+        (() => {
+            var conf = __webpack_require__(81), engine = __webpack_require__(557), utility = __webpack_require__(871), douyin = __webpack_require__(954), param = {
+                yxgs: 500,
+                czjg1: 3,
+                czjg2: 6,
+                gksj1: 5,
+                gksj2: 10,
+                tglv: !0,
+                dz: 45,
+                gz: 5,
+                pl: 35,
+                txdz: 60,
+                pldz: 80,
+                plhs: conf.commonts,
+                gjcs: [ "77396094576", "60866194851" ],
+                pltp: !0
+            }, znzf = {
+                banben: parseFloat(context.getPackageManager().getPackageInfo("com.ss.android.ugc.aweme", 0).versionName) < 27.4,
+                init() {
+                    return !(!douyin.init() || ("undefined" != typeof ENV_CONF && Object.assign(param, ENV_CONF),
+                    0 < param.pl && param.plhs.length < 1 ? (alert("请设置评论话术"), 1) : douyin.isRecommend() ? (utility.toast("开始任务:智能涨粉"),
+                    engine.sleep(1), device.keepScreenDim(), douyin.popupAndClose(),
+                    0) : (alert("请在抖音首页运行"), 1)));
+                },
+                isUserList() {
+                    var tab = className("androidx.appcompat.app.ActionBar$Tab").visibleToUser().selected().findOnce();
+                    return null !== tab && (null !== tab.findOne(textContains("粉丝")) || null !== tab.findOne(textContains("关注")));
+                },
+                toUserList() {
+                    for (;;) {
+                        if (sleep(2e3), this.isUserList()) return;
+                        back(), sleep(1e3);
+                    }
+                },
+                execUser() {
+                    if (engine.sleep(param.czjg1, param.czjg2), !douyin.isHome()) return utility.toast("进入主页失败"),
+                 !1;
+                    if (null !== text("私密账号").visibleToUser().findOnce() || null !== text("帐号已被封禁").visibleToUser().findOnce()) return utility.toast("私密或已封禁账号,跳过"),
+                    !1;
+                    if (param.tglv && null !== className("android.widget.TextView").visibleToUser().id(douyin.getNode("user.lanv").id).findOnce()) return utility.toast("蓝v用户,跳过!"),
+                    !1;
+                    let fansNum = 0;
+                    var fansNode = id(douyin.getNode("user.fansnum").id).visibleToUser().findOnce();
+                    fansNode && (fansText = fansNode.text(), fansNum = parseFloat(fansText),
+                    0 <= fansText.indexOf("w") || 0 <= fansText.indexOf("万")) && (fansNum *= 1e4);
+                    let gzNum = 0;
+                    fansNode = id(douyin.getNode("user.gznum").id).visibleToUser().findOnce();
+                    if (fansNode && (gzText = fansNode.text(), gzNum = parseFloat(gzText),
+                    0 <= gzText.indexOf("w") || 0 <= gzText.indexOf("万")) && (gzNum *= 1e4),
+                    gzNum - fansNum < 1e3) return !1;
+                    fansNode = textContains("作品").visibleToUser().findOnce();
+                    let videoNum = 0;
+                    if ((videoNum = fansNode ? parseInt(fansNode.text().replace(/[^0-9]/gi, "")) : videoNum) < 1 || isNaN(videoNum)) return utility.toast("该用户没有作品或非正常用户,跳过"),
+                    !1;
+                    this.banben && utility.checkProbability(param.txdz, "头像点赞") && (douyin.execTxdz(),
+                    engine.sleepMs(1e3, 2e3)), utility.checkProbability(param.gz, "关注") && ((followBtn = id(douyin.getNode("user.followBtn").id).visibleToUser().findOnce()) ? (utility.toast("执行关注!"),
+                    followBtn.click(), engine.sleepMs(500, 1e3), gzCount++, (followBtn = desc("更多,已展开").visibleToUser().findOne(5e3)) && (followBtn.click(),
+                    engine.sleepMs(500, 1e3))) : utility.toast("不关注!"));
+                    var followBtn = utility.checkProbability(param.dz, "点赞"), isPl = utility.checkProbability(param.pl, "评论");
+                    if (followBtn || isPl) {
+                        fansNode.selected() || (engine.boundsClick(fansNode.bounds()),
+                        engine.sleepMs(1e3, 2e3)), engine.shortSlide();
+                        var fansNode = id("com.ss.android.ugc.aweme:id/container").visibleToUser().find();
+                        if (!fansNode.empty()) {
+                            let video = fansNode[random(0, fansNode.length - 1)];
+                            video = video.findOne(className("android.view.View")), sleep(1e3),
+                            video && video.clickable() && video.click() && douyin.IsVideoDelay(5e3) ? (fansNode = random(param.gksj1, param.gksj2),
+                            utility.toast("观看视频:" + fansNode + " 秒"), engine.sleep(fansNode),
+                            followBtn ? (douyin.execLike(), dzCount++) : utility.toast("不点赞"),
+                            isPl && douyin.canComment() ? (fansNode = utility.checkProbability(param.pldz, "评论点赞"),
+                            douyin.sendComment(param.plhs, isPl, fansNode, param.pltp),
+                            plCount++) : utility.toast("不评论")) : (utility.toast("打开视频失败!"),
+                            back(), sleep(1e3));
+                        }
+                    }
+                    return !0;
+                },
+                dbzhgjc(gjc) {
+                    engine.sleepMs(1e3, 2e3), id("com.ss.android.ugc.aweme:id/et_search_kw").visibleToUser().findOne().setText(gjc),
+                    engine.sleepMs(1e3, 2e3);
+                    var b1 = text("搜索").visibleToUser().findOne().bounds(), b1 = (engine.boundsClick(b1),
+                    engine.sleepMs(3e3, 4e3), text("用户").visibleToUser().findOne().bounds()), b1 = (engine.boundsClick(b1),
+                    engine.sleepMs(3e3, 4e3), descContains(gjc).visibleToUser().findOne(5e3));
+                 return null === b1 ? (alert("没有找到对标账号", "请检查对标账号 " + gjc + " 是否输入正确!"),
+                    !1) : (engine.boundsClick(b1.bounds()), engine.sleepMs(3e3, 4e3),
+                    text("粉丝").visibleToUser().findOne().parent().click(), engine.sleepMs(3e3, 4e3),
+                    !!id("com.ss.android.ugc.aweme:id/root_layout").exists() || (alert("打开粉丝列表失败", "对标账号 " + gjc + " 粉丝列表可能设置隐私了!"),
+                    !1));
+                },
+                run() {
+                    if (this.init()) {
+                        let runCount = dzCount = gzCount = plCount = 0;
+                        var userContents = [];
+                        let gjcsCount = 0, dyc = !0;
+                        for (;;) {
+                            if (dyc && (descStartsWith("搜索").descEndsWith("按钮").visibleToUser().findOne().parent().click(),
+                            dyc = !1, !this.dbzhgjc(param.gjcs[gjcsCount]))) break;
+                            if (runCount >= param.yxgs) return device.cancelKeepingAwake(),
+                            void alert("恭喜任务完成!", "本次任务共完成\n点赞" + dzCount + "次\n关注" + gzCount + "次\n评论" + plCount + "次");
+                            let listBox = className("androidx.recyclerview.widget.RecyclerView").visibleToUser().findOne();
+                            if (!listBox) return void utility.toast("没有找到用户列表!");
+                            var listBoxTop = listBox.bounds().top, childCount = listBox.childCount();
+                            for (let i = 0; i < childCount - 1; i++) {
+                                if (runCount >= param.yxgs) return device.cancelKeepingAwake(),
+                                void alert("恭喜任务完成!", "本次任务共完成\n点赞" + dzCount + "次\n关注" + gzCount + "次\n评论" + plCount + "次");
+                                utility.toast("已执行用户 " + runCount + " 条,任务数" + param.yxgs);
+                                var child = listBox.child(i);
+                                if (null != child && !(listBoxTop >= child.bounds().top || child.findOne(desc("已关注")))) {
+                                    var userNode = child.findOne(className("android.widget.TextView"));
+                                    if (userNode) {
+                                        userNode = userNode.text();
+                                        if (!utility.isEmpty(userNode) && !userContents.includes(userNode)) {
+                                            console.log(userNode), 20 <= userContents.length && userContents.shift(),
+                                            userContents.push(userNode);
+                                            try {
+                                                child.click(), this.execUser() && runCount++;
+                                            } catch (error) {
+                                                console.log("用户操作失败:", error);
+                                            }
+                                            if (utility.toast("返回用户列表"), this.toUserList(),
+                                            engine.sleepMs(2e3, 3e3), !(listBox = className("androidx.recyclerview.widget.RecyclerView").visibleToUser().findOne())) return void utility.toast("没有找到用户列表!");
+                                        }
+                                    } else console.log("没有获取到用户信息");
+                                }
+                            }
+                            if (!listBox.scrollForward()) {
+                                if (++gjcsCount >= param.gjcs.length) {
+                                    alert("对标账号已全部运行完!", "本次任务共完成\n点赞" + dzCount + "次\n关注" + gzCount + "次\n评论" + plCount + "次");
+                                    break;
+                                }
+                                if (engine.sleepMs(3e3, 4e3), back(), engine.sleepMs(3e3, 4e3),
+                             back(), engine.sleepMs(3e3, 4e3), !this.dbzhgjc(param.gjcs[gjcsCount])) break;
+                            }
+                            engine.sleepMs(2500, 3500);
+                        }
+                    }
+                }
+            };
+            try {
+                znzf.run();
+            } catch (error) {
+                utility.error(conf.packageName, error);
+            } finally {
+                engine.exit();
+            }
+        })();
+    })();

+ 13 - 0
dtok-app/app/src/main/assets/project/project.json

@@ -0,0 +1,13 @@
+{
+  "assets": [],
+  "build": {
+    "build_id": "B883A485-9",
+    "build_number": 1,
+    "build_time": 1543638246643
+  },
+  "main": "main.js",
+  "name": "打包测试",
+  "packageName": "xx.xx",
+  "versionCode": 1,
+  "versionName": "1.0.0"
+}

+ 167 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/Api.java

@@ -0,0 +1,167 @@
+package com.cj.autojs.dtok;
+
+import android.content.Intent;
+
+import com.cj.autojs.dtok.config.UrlConfig;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import kotlin.jvm.internal.Intrinsics;
+import okhttp3.Callback;
+import okhttp3.FormBody;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class Api {
+
+    private static long expireAt;
+    private static String token;
+    public static final Api INSTANCE = new Api();
+    private static String name = "";
+
+    private Api() {
+    }
+
+    public final String getToken() {
+        return token;
+    }
+
+    public final void setToken(String str) {
+        token = str;
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(String str) {
+        Intrinsics.checkNotNullParameter(str, "<set-?>");
+        name = str;
+    }
+
+    public final long getExpireAt() {
+        return expireAt;
+    }
+
+    public final void setExpireAt(long j) {
+        expireAt = j;
+    }
+
+    private OkHttpClient client() {
+
+        OkHttpClient build = new OkHttpClient.Builder()
+                .addInterceptor(new TokenInterceptor())
+//                .authenticator(new TokenAuthenticator())
+                .followRedirects(false)
+                .followSslRedirects(false)
+                .connectTimeout(6000L, TimeUnit.MILLISECONDS).readTimeout(6000L, TimeUnit.MILLISECONDS)
+                .writeTimeout(6000L, TimeUnit.MILLISECONDS).build();
+        Intrinsics.checkNotNullExpressionValue(build, "Builder()\n            .c…写入超时\n            .build()");
+        return build;
+    }
+
+//    public class TokenAuthenticator implements Authenticator {
+//
+//        @Nullable
+//        @Override
+//        public Request authenticate(@Nullable Route route, Response response) throws IOException {
+//            int code = response.code();
+//            if (code == 401) {
+//                //TODO Token过期
+//            }
+//            return response.request();
+//        }
+//    }
+
+    public class TokenInterceptor implements Interceptor {
+        @Override
+        public Response intercept(Chain chain) throws IOException {
+            Response response = chain.proceed(chain.request());
+            if (response.code() == 401) {//401
+                Intent i = new Intent(App.INSTANCE.getMContext(), LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+                i.putExtra("loginError", "登录失效");
+                (App.INSTANCE.getMContext()).startActivity(i);
+            }
+            return response;
+        }
+    }
+
+
+    private final Request.Builder request() {
+        Request.Builder builder = new Request.Builder();
+        String str = token;
+        if (str != null) {
+            Intrinsics.checkNotNull(str);
+            builder.addHeader("satoken", str);
+        }
+        builder.addHeader("X-AGENT-ID", BuildConfig.AGENT_USER_ID);
+        builder.addHeader("X-PRODUCT-NAME", BuildConfig.PRODUCT_NAME);
+
+        return builder;
+    }
+
+    public final void login(String username, String password, Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        client.newCall(request.url(UrlConfig.LOGIN_URL).post(new FormBody.Builder().add("username", username)
+                .add("password", password).add("loginDevice", UrlConfig.DEVICE).build()).build()).enqueue(callback);
+    }
+
+    public final void checkLogin(Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        client.newCall(request.url(UrlConfig.BASE_API + "checkLogin").get().build()).enqueue(callback);
+    }
+
+    public final void checkRegister(String uuid, String androidId, Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        String url = UrlConfig.BASE_API + String.format("checkRegister/%s/%s", uuid, androidId);
+        client.newCall(request.url(url).get().build()).enqueue(callback);
+    }
+
+    public final void registerDevice(String deviceName, String deviceVersion,
+                                     String deviceBrand, String imei, Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        String url = UrlConfig.BASE_API + String.format("registerDevice/%s", api.getToken());
+        FormBody.Builder formBody = new FormBody.Builder();
+        formBody.add("deviceName", deviceName);
+        formBody.add("deviceVersion", deviceVersion);
+        formBody.add("deviceBrand", deviceBrand);
+        formBody.add("androidId", imei);
+        client.newCall(request.url(url).post(formBody.build()).build()).enqueue(callback);
+    }
+
+    public final void unBundleDevice(String uuid, Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        String url = UrlConfig.BASE_API + String.format("registerDevice/%s", uuid);
+        client.newCall(request.url(url).get().build()).enqueue(callback);
+    }
+
+    public final void getCommonItem(Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        String url = UrlConfig.BASE_API + "getCommonItem";
+        client.newCall(request.url(url).get().build()).enqueue(callback);
+    }
+
+    public final void getScript(String uuid, String module, Callback callback) {
+        Api api = INSTANCE;
+        OkHttpClient client = api.client();
+        Request.Builder request = api.request();
+        String url = UrlConfig.BASE_API + "getExecScript/" + uuid + "?module=" + module;
+        client.newCall(request.url(url).get().build()).enqueue(callback);
+    }
+
+}

+ 79 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/App.kt

@@ -0,0 +1,79 @@
+package com.cj.autojs.dtok
+
+import android.app.Application
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.drawable.Drawable
+import android.net.Uri
+import android.view.View
+import android.widget.ImageView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.target.SimpleTarget
+import com.bumptech.glide.request.transition.Transition
+import com.stardust.app.GlobalAppContext
+import com.stardust.autojs.core.ui.inflater.ImageLoader
+import com.stardust.autojs.core.ui.inflater.util.Drawables
+import com.cj.autojs.dtok.autojs.DemoAutoJs
+import com.cj.autojs.dtok.autojs.GlobalKeyObserver
+
+/**
+ * Created by Stardust on 2017/7/1.
+ */
+
+class App : Application() {
+
+
+    companion object INSTANCE {
+        var mContext: Context? = null
+    }
+
+    override fun onCreate() {
+        super.onCreate()
+        GlobalAppContext.set(this)
+        DemoAutoJs.initInstance(this)
+        GlobalKeyObserver.init()
+        Drawables.setDefaultImageLoader(object : ImageLoader {
+            override fun loadInto(imageView: ImageView, uri: Uri) {
+                Glide.with(this@App)
+                        .load(uri)
+                        .into(imageView)
+            }
+
+            override fun loadIntoBackground(view: View, uri: Uri) {
+                Glide.with(this@App)
+                        .load(uri)
+                        .into(object : SimpleTarget<Drawable>() {
+                            override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>) {
+                                view.background = resource
+                            }
+                        })
+            }
+
+            override fun load(view: View, uri: Uri): Drawable {
+                throw UnsupportedOperationException()
+            }
+
+            override fun load(view: View, uri: Uri, drawableCallback: ImageLoader.DrawableCallback) {
+                Glide.with(this@App)
+                        .load(uri)
+                        .into(object : SimpleTarget<Drawable>() {
+                            override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>) {
+                                drawableCallback.onLoaded(resource)
+                            }
+                        })
+            }
+
+            override fun load(view: View, uri: Uri, bitmapCallback: ImageLoader.BitmapCallback) {
+                Glide.with(this@App)
+                        .asBitmap()
+                        .load(uri)
+                        .into(object : SimpleTarget<Bitmap>() {
+                            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>) {
+                                bitmapCallback.onLoaded(resource)
+                            }
+                        })
+            }
+        })
+    }
+
+}

+ 38 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/BaseActivity.java

@@ -0,0 +1,38 @@
+package com.cj.autojs.dtok;
+
+import android.app.NotificationManager;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.afollestad.materialdialogs.DialogAction;
+import com.afollestad.materialdialogs.MaterialDialog;
+import com.blankj.utilcode.util.PermissionUtils;
+import com.stardust.app.GlobalAppContext;
+import com.stardust.autojs.util.FloatingPermission;
+import com.stardust.view.accessibility.AccessibilityService;
+import com.stardust.view.accessibility.AccessibilityServiceUtils;
+
+public class BaseActivity  extends AppCompatActivity {
+
+    public final String getVersionName() {
+        try {
+            String str = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
+            return str;
+        } catch (Exception unused) {
+            return "";
+        }
+    }
+
+
+
+
+
+
+}

+ 50 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/DrawOverlaysPermission.java

@@ -0,0 +1,50 @@
+package com.cj.autojs.dtok;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+import androidx.activity.result.ActivityResultLauncher;
+
+import com.cj.autojs.dtok.util.PermissionsSettingsUtil;
+
+import kotlin.jvm.internal.Intrinsics;
+
+/* compiled from: DrawOverlaysPermission.kt */
+/* loaded from: classes.dex */
+public final class DrawOverlaysPermission {
+    public static final DrawOverlaysPermission INSTANCE = new DrawOverlaysPermission();
+
+    private DrawOverlaysPermission() {
+    }
+
+    public final boolean isCanDrawOverlays(Context context) {
+        Intrinsics.checkNotNullParameter(context, "context");
+        if (Build.VERSION.SDK_INT >= 23) {
+            return Settings.canDrawOverlays(context);
+        }
+        return true;
+    }
+
+    public final void launchCanDrawOverlaysSettings(ActivityResultLauncher<Intent> activityResultLauncher, String packageName) {
+        Intrinsics.checkNotNullParameter(activityResultLauncher, "<this>");
+        Intrinsics.checkNotNullParameter(packageName, "packageName");
+        try {
+            activityResultLauncher.launch(getCanDrawOverlaysIntent(packageName));
+        } catch (Exception e) {
+            e.printStackTrace();
+            PermissionsSettingsUtil.INSTANCE.launchAppPermissionsSettings(activityResultLauncher, packageName);
+        }
+    }
+
+    public final Intent getCanDrawOverlaysIntent(String packageName) {
+        Intrinsics.checkNotNullParameter(packageName, "packageName");
+        if (Build.VERSION.SDK_INT >= 23) {
+            Intent intent = new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION");
+            intent.setData(Uri.parse("package:" + packageName));
+            return intent;
+        }
+        return null;
+    }
+}

+ 203 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/LoginActivity.java

@@ -0,0 +1,203 @@
+package com.cj.autojs.dtok;
+
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.HideReturnsTransformationMethod;
+import android.text.method.PasswordTransformationMethod;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ToggleButton;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.cj.autojs.dtok.entity.User;
+import com.cj.autojs.dtok.service.ForegroundService;
+import com.cj.autojs.dtok.util.SharedPreferencesUtils;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+public class LoginActivity extends BaseActivity {
+
+    EditText usernameEdit;
+
+    EditText passwordEdit;
+
+    Button loginBtn;
+
+
+    ToggleButton clearUser;
+
+    ToggleButton togglePwd;
+
+    ConstraintLayout loginLayout;
+
+    TextView textView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.login_activity);
+        textView = findViewById(R.id.app_version);
+        textView.setText(getVersionName());
+        ForegroundService.stop(LoginActivity.this);
+        Intent intent = getIntent();
+        if (intent != null) {
+            Bundle bundle = intent.getExtras();
+            if (bundle != null) {
+                String oldData = bundle.getString("loginError");
+                Toast.makeText(this, oldData, Toast.LENGTH_SHORT).show();
+                // 使用oldData进行操作
+            }
+        }
+
+        initUi();
+        initEvent();
+    }
+
+    public void initUi() {
+//        Log.d("GET_DEVICE_ID", DeviceUtil.getDeviceIMEI(this));
+
+        usernameEdit = findViewById(R.id.login_user);
+        passwordEdit = findViewById(R.id.login_passwd);
+        loginBtn = findViewById(R.id.Login_btn_Login);
+        togglePwd = findViewById(R.id.togglePwd);
+        clearUser = findViewById(R.id.clearUser);
+        loginLayout = findViewById(R.id.loginLayout);
+
+        Drawable drawable = getResources().getDrawable(R.drawable.ic_username, null);
+        drawable.setBounds(0, 0, 70, 70);
+        usernameEdit.setCompoundDrawables(drawable, null, null, null);
+        Drawable drawable2 = getResources().getDrawable(R.drawable.ic_password, null);
+        drawable2.setBounds(0, 0, 70, 70);
+        passwordEdit.setCompoundDrawables(drawable2, null, null, null);
+        usernameEdit.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+                clearUser.setChecked(!TextUtils.isEmpty(charSequence));
+            }
+
+            @Override
+            public void afterTextChanged(Editable editable) {
+
+            }
+        });
+        clearUser.setOnCheckedChangeListener((compoundButton, b) -> {
+            if (b) {
+                return;
+            }
+            passwordEdit.setText(null);
+            usernameEdit.setText(null);
+            usernameEdit.setFocusable(true);
+            usernameEdit.setFocusableInTouchMode(true);
+            usernameEdit.requestFocus();
+            usernameEdit.requestFocusFromTouch();
+        });
+        togglePwd.setOnCheckedChangeListener((compoundButton, b) -> {
+            if (b) {
+                passwordEdit.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
+            } else {
+                passwordEdit.setTransformationMethod(PasswordTransformationMethod.getInstance());
+            }
+
+        });
+    }
+
+    public void initEvent() {
+//        ProgressDialog progress = new ProgressDialog(this);
+
+        loginBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if (TextUtils.isEmpty(usernameEdit.getText())) {
+                    Toast.makeText(LoginActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();
+                    return;
+                }
+                if (TextUtils.isEmpty(passwordEdit.getText())) {
+                    Toast.makeText(LoginActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();
+                    return;
+                }
+                new Thread(() -> {
+
+                    Api.INSTANCE.login(usernameEdit.getText().toString(), passwordEdit.getText().toString(), new Callback() {
+                        @Override
+                        public void onFailure(Call call, IOException e) {
+                            LoginActivity.this.runOnUiThread(() -> clearUser.toggle());
+                        }
+
+                        @Override
+                        public void onResponse(Call call, Response response) throws IOException {
+                            ResponseBody responseBody = response.body();
+                            if (responseBody == null) {
+                                LoginActivity.this.runOnUiThread(() -> {
+                                    clearUser.toggle();
+                                    Toast.makeText(LoginActivity.this, "数据异常", Toast.LENGTH_SHORT).show();
+                                });
+                            } else {
+                                String jsonStr = responseBody.string();
+                                try {
+                                    JSONObject logonObj = new JSONObject(jsonStr);
+                                    if (!logonObj.getBoolean("success")) {
+                                        LoginActivity.this.runOnUiThread(() -> {
+                                            try {
+                                                Toast.makeText(LoginActivity.this, logonObj.getString("message"), Toast.LENGTH_SHORT).show();
+                                            } catch (JSONException e) {
+                                                throw new RuntimeException(e);
+                                            }
+                                        });
+                                    } else {
+                                        JSONObject dataObj = logonObj.getJSONObject("data");
+
+                                        Api.INSTANCE.setToken(dataObj.getString("token"));
+                                        JSONObject userObj = dataObj.getJSONObject("user");
+                                        User user = new User();
+                                        user.setId(userObj.getInt("id"));
+                                        user.setName(userObj.getString("name"));
+                                        user.setExpireAt(userObj.getString("expireAt"));
+                                        user.setExpireTime(userObj.getLong("expireTime"));
+                                        user.setUsername(userObj.getString("username"));
+                                        user.setStatus(userObj.getBoolean("status"));
+                                        user.setMaxDevices(userObj.getInt("maxDevices"));
+                                        user.setStatus(userObj.getBoolean("status"));
+                                        SharedPreferencesUtils.saveUserInfo(LoginActivity.this, user);
+                                        SharedPreferencesUtils.saveString(LoginActivity.this, "token", dataObj.getString("token"));
+                                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
+                                        startActivity(intent);
+                                        finish();
+                                    }
+                                } catch (JSONException e) {
+                                    LoginActivity.this.runOnUiThread(() -> {
+                                        Toast.makeText(LoginActivity.this, "系统错误,请稍后再试", Toast.LENGTH_SHORT).show();
+                                    });
+                                }
+                            }
+
+
+                        }
+                    });
+                }).start();
+            }
+        });
+    }
+
+}

+ 216 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/MainActivity.java

@@ -0,0 +1,216 @@
+package com.cj.autojs.dtok;
+
+import android.annotation.SuppressLint;
+import android.app.NotificationManager;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+import android.webkit.ConsoleMessage;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.afollestad.materialdialogs.DialogAction;
+import com.afollestad.materialdialogs.MaterialDialog;
+import com.blankj.utilcode.util.PermissionUtils;
+import com.stardust.app.GlobalAppContext;
+import com.stardust.autojs.util.FloatingPermission;
+import com.stardust.view.accessibility.AccessibilityService;
+import com.stardust.view.accessibility.AccessibilityServiceUtils;
+import com.cj.autojs.dtok.config.UrlConfig;
+import com.cj.autojs.dtok.jsinterface.JsInterface;
+import com.cj.autojs.dtok.service.ForegroundService;
+import com.cj.autojs.dtok.util.SharedPreferencesUtils;
+
+public class MainActivity extends AppCompatActivity {
+
+    private static final String TAG = "MainActivity";
+    WebView webView;
+    boolean isNotificationEnabled;
+
+    private boolean isHome = true;
+
+
+    public  void openDialogAccessibility() {
+        if (checkAccessibility()) {
+            return;
+        }
+        new MaterialDialog.Builder(this).title(R.string.text_need_to_enable_accessibility_service).content(R.string.explain_accessibility_permission).positiveText(R.string.text_go_to_setting).negativeText(R.string.text_cancel).onPositive(new MaterialDialog.SingleButtonCallback() { // from class: com.phgors.auto.ui.BaseActivity$$ExternalSyntheticLambda3
+            @Override // com.afollestad.materialdialogs.MaterialDialog.SingleButtonCallback
+            public final void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
+                openAccessibility();
+            }
+        }).show();
+    }
+    public final void openAccessibility() {
+        if (checkAccessibility()) {
+            return;
+        }
+        try {
+            AccessibilityServiceUtils.INSTANCE.goToAccessibilitySetting(this);
+        } catch (ActivityNotFoundException unused) {
+            GlobalAppContext.toast((int) R.string.go_to_accessibility_settings);
+        }
+    }
+
+
+    public final boolean checkDrawOverlay() {
+        return FloatingPermission.canDrawOverlays(GlobalAppContext.get());
+    }
+
+    public final boolean checkAccessibility() {
+        AccessibilityServiceUtils accessibilityServiceUtils = AccessibilityServiceUtils.INSTANCE;
+        Context context = GlobalAppContext.get();
+        return accessibilityServiceUtils.isAccessibilityServiceEnabled(context, AccessibilityService.class);
+    }
+
+    public void requestWindowPermission() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            PermissionUtils.requestDrawOverlays(new PermissionUtils.SimpleCallback() {
+                @Override
+                public void onGranted() {
+
+                }
+
+                @Override
+                public void onDenied() {
+
+                    Toast.makeText(MainActivity.this, "申请失败", Toast.LENGTH_SHORT).show();
+                }
+            });
+        }
+    }
+
+    public final boolean isNotificationEnabled() {
+        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        return notificationManager.areNotificationsEnabled();
+    }
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        webView = findViewById(R.id.webView);
+        initWebView();
+//        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+//        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+//            isNotificationEnabled = notificationManager.areNotificationsEnabled();
+//        }
+//        if (!isNotificationEnabled) {
+//            this.jumpNotificationSetting();
+//        }
+
+        ForegroundService.start(MainActivity.this);
+    }
+
+
+
+
+
+    public final boolean isHome() {
+        return this.isHome;
+    }
+
+    public final void setHome(boolean z) {
+        this.isHome = z;
+    }
+
+
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (Api.INSTANCE.getToken() == null && SharedPreferencesUtils.getString(MainActivity.this, "token", null) == null) {
+            startActivity(new Intent(this, LoginActivity.class));
+            finish();
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (!this.isHome && webView.canGoBack()) {
+            webView.goBack();
+        } else {
+            moveTaskToBack(true);
+        }
+    }
+
+
+    public void jumpNotificationSetting() {
+        final ApplicationInfo applicationInfo = getApplicationInfo();
+        try {
+            Intent intent = new Intent();
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
+            intent.putExtra("app_package", applicationInfo.packageName);
+            intent.putExtra("android.provider.extra.APP_PACKAGE", applicationInfo.packageName);
+            intent.putExtra("app_uid", applicationInfo.uid);
+            startActivity(intent);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            Intent intent = new Intent();
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
+            intent.setData(Uri.fromParts("package", applicationInfo.packageName, null));
+            startActivity(intent);
+        }
+    }
+
+    @SuppressLint("SetJavaScriptEnabled")
+    private void initWebView() {
+        //设置支持JS
+        webView.getSettings().setJavaScriptEnabled(true);
+        // 设置支持本地存储
+        webView.getSettings().setDatabaseEnabled(true);
+        //取得缓存路径
+        String path = this.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();
+        //设置路径
+        webView.getSettings().setDatabasePath(path);
+        //设置支持DomStorage
+        webView.getSettings().setDomStorageEnabled(true);
+        //设置存储模式
+        webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
+        //设置适应屏幕
+        webView.getSettings().setUseWideViewPort(true);
+        webView.getSettings().setLoadWithOverviewMode(true);
+        webView.getSettings().setSupportZoom(true);
+        webView.getSettings().setBuiltInZoomControls(true);
+        webView.getSettings().setDisplayZoomControls(false);
+        //设置缓存
+//        webView.getSettings().setAppCacheEnabled(true);
+        webView.requestFocus();
+        webView.addJavascriptInterface(new JsInterface(this, webView), "dtokjs");
+        //下面三个各种监听
+        webView.setWebChromeClient(new WebChromeClient() {
+            public boolean onConsoleMessage(ConsoleMessage cm) {
+                Log.d("DTOK_WEB", cm.message() + " -- From line "
+                        + cm.lineNumber() + " of "
+                        + cm.sourceId());
+                return true;
+            }
+
+
+        });
+//        webView.setDownloadListener(dl);
+        webView.setWebViewClient(new WebViewClient() {
+            @Override
+            public void onPageFinished(WebView view, String url) {
+                super.onPageFinished(view, url);
+                Log.d(TAG, "onPageFinished: 页面加载完成");
+            }
+        });
+        webView.loadUrl(UrlConfig.UI_URL);
+    }
+
+
+
+
+}

+ 50 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/Pref.kt

@@ -0,0 +1,50 @@
+package com.cj.autojs.dtok
+
+import android.content.SharedPreferences
+import android.preference.PreferenceManager
+
+import com.stardust.app.GlobalAppContext
+
+/**
+ * Created by Stardust on 2017/12/8.
+ */
+
+object Pref {
+
+    private const val KEY_FIRST_USING = "key_first_using"
+    private var sPreferences: SharedPreferences? = null
+
+    val preferences: SharedPreferences
+        get() {
+            return sPreferences ?: run {
+                val pref = PreferenceManager.getDefaultSharedPreferences(GlobalAppContext.get())
+                sPreferences = pref
+                pref
+            }
+        }
+
+    val isFirstUsing: Boolean
+        get() {
+            val firstUsing = preferences.getBoolean(KEY_FIRST_USING, true)
+            if (firstUsing) {
+                preferences.edit().putBoolean(KEY_FIRST_USING, false).apply()
+            }
+            return firstUsing
+        }
+
+    private fun getString(res: Int): String {
+        return GlobalAppContext.getString(res)
+    }
+
+    fun shouldEnableAccessibilityServiceByRoot(): Boolean {
+        return preferences.getBoolean(getString(R.string.key_enable_accessibility_service_by_root), false)
+    }
+
+    fun shouldHideLogs(): Boolean {
+        return preferences.getBoolean(getString(R.string.key_dont_show_main_activity), false)
+    }
+
+    fun shouldStopAllScriptsWhenVolumeUp(): Boolean {
+        return preferences.getBoolean(getString(R.string.key_use_volume_control_running), true)
+    }
+}

+ 91 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/SplashActivity.java

@@ -0,0 +1,91 @@
+package com.cj.autojs.dtok;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.gson.Gson;
+import com.cj.autojs.dtok.entity.User;
+import com.cj.autojs.dtok.util.SharedPreferencesUtils;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Response;
+
+public class SplashActivity extends BaseActivity {
+
+    TextView textView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.splash_screen);
+        textView = findViewById(R.id.app_version);
+        textView.setText(getVersionName());
+        new Handler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                checkLogin();
+            }
+        }, 2000);
+    }
+
+
+    public void checkLogin() {
+        Intent toLogin = new Intent(this, LoginActivity.class);
+        Intent toMain = new Intent(this, MainActivity.class);
+        if (SharedPreferencesUtils.contains(this, "token")) {
+            Api.INSTANCE.setToken(SharedPreferencesUtils.getString(this, "token", ""));
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    Api.INSTANCE.checkLogin(new Callback() {
+                        @Override
+                        public void onFailure(Call call, IOException e) {
+                            SplashActivity.this.runOnUiThread(() -> {
+                                Toast.makeText(SplashActivity.this, "登录异常", Toast.LENGTH_SHORT).show();
+                            });
+                            startActivity(toLogin);
+                            finish();
+                        }
+
+                        @Override
+                        public void onResponse(Call call, Response response) throws IOException {
+                            if (response.body() != null) {
+                                try {
+                                    JSONObject object = new JSONObject(response.body().string());
+                                    if (object.getBoolean("success")) {
+                                        Gson gson = new Gson();
+                                        User user = gson.fromJson(object.getJSONObject("data").toString(), User.class);
+                                        SharedPreferencesUtils.saveUserInfo(SplashActivity.this, user);
+                                        startActivity(toMain);
+                                        finish();
+                                        return;
+                                    }
+                                } catch (JSONException e) {
+                                    throw new RuntimeException(e);
+                                }
+
+                            }
+                            startActivity(toLogin);
+                            finish();
+                        }
+                    });
+                }
+            }).start();
+        }else{
+            startActivity(toLogin);
+            finish();
+        }
+    }
+
+}

+ 53 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/AccessibilityServiceTool.kt

@@ -0,0 +1,53 @@
+package com.cj.autojs.dtok.autojs
+
+import android.accessibilityservice.AccessibilityService
+import android.content.Context
+import android.content.Intent
+import android.text.TextUtils
+
+import com.stardust.app.GlobalAppContext
+import com.stardust.autojs.core.util.ProcessShell
+
+import java.util.Locale
+
+/**
+ * Created by Stardust on 2017/7/1.
+ */
+
+object AccessibilityServiceTool {
+
+    private val cmd = "enabled=$(settings get secure enabled_accessibility_services)\n" +
+            "pkg=%s\n" +
+            "if [[ \$enabled == *\$pkg* ]]\n" +
+            "then\n" +
+            "echo already_enabled\n" +
+            "else\n" +
+            "enabled=\$pkg:\$enabled\n" +
+            "settings put secure enabled_accessibility_services \$enabled\n" +
+            "fi"
+
+    fun enableAccessibilityServiceByRoot(context: Context, accessibilityService: Class<out AccessibilityService>): Boolean {
+        val serviceName = context.packageName + "/" + accessibilityService.name
+        return try {
+            TextUtils.isEmpty(ProcessShell.execCommand(String.format(Locale.getDefault(), cmd, serviceName), true).error)
+        } catch (ignored: Exception) {
+            false
+        }
+
+    }
+
+    fun enableAccessibilityServiceByRootAndWaitFor(context: Context, timeOut: Long): Boolean {
+        if (enableAccessibilityServiceByRoot(context, com.stardust.view.accessibility.AccessibilityService::class.java)) {
+            com.stardust.view.accessibility.AccessibilityService.waitForEnabled(timeOut)
+            return true
+        }
+        return false
+    }
+
+    fun goToAccessibilitySetting() {
+//        GlobalAppContext.get().startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+        GlobalAppContext.get().startActivity(Intent("android.settings.ACCESSIBILITY_SETTINGS").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+    }
+
+
+}

+ 105 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/DemoAutoJs.kt

@@ -0,0 +1,105 @@
+package com.cj.autojs.dtok.autojs
+
+import android.annotation.SuppressLint
+import android.app.Application
+import android.content.Context
+import com.stardust.app.GlobalAppContext
+import com.stardust.autojs.AutoJs
+import com.stardust.autojs.runtime.api.AppUtils
+import com.stardust.autojs.runtime.exception.ScriptException
+import com.stardust.autojs.runtime.exception.ScriptInterruptedException
+import com.stardust.autojs.script.JavaScriptSource
+import com.stardust.view.accessibility.AccessibilityService
+import com.stardust.view.accessibility.AccessibilityServiceUtils
+import com.cj.autojs.dtok.Pref
+import com.cj.autojs.dtok.R
+
+
+/**
+ * Created by Stardust on 2017/4/2.
+ */
+
+class DemoAutoJs private constructor(application: Application) : AutoJs(application) {
+
+    init {
+        scriptEngineService.registerGlobalScriptExecutionListener(ScriptExecutionGlobalListener())
+    }
+
+    override fun createAppUtils(context: Context): AppUtils {
+        return AppUtils(context, context.packageName + ".fileprovider")
+    }
+
+
+    override fun ensureAccessibilityServiceEnabled() {
+        if (AccessibilityService.instance != null) {
+            return
+        }
+        var errorMessage: String? = null
+        if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(application, AccessibilityService::class.java)) {
+            errorMessage = GlobalAppContext.getString(R.string.text_auto_operate_service_enabled_but_not_running)
+        } else {
+            if (Pref.shouldEnableAccessibilityServiceByRoot()) {
+                if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(application, 2000)) {
+                    errorMessage = GlobalAppContext.getString(R.string.text_enable_accessibility_service_by_root_timeout)
+                }
+            } else {
+                errorMessage = GlobalAppContext.getString(R.string.text_no_accessibility_permission)
+            }
+        }
+        if (errorMessage != null) {
+            AccessibilityServiceTool.goToAccessibilitySetting()
+            throw ScriptException(errorMessage)
+        }
+    }
+
+    override fun waitForAccessibilityServiceEnabled() {
+        if (AccessibilityService.instance != null) {
+            return
+        }
+        var errorMessage: String? = null
+        if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(application, AccessibilityService::class.java)) {
+            errorMessage = GlobalAppContext.getString(R.string.text_auto_operate_service_enabled_but_not_running)
+        } else {
+            if (Pref.shouldEnableAccessibilityServiceByRoot()) {
+                if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(application, 2000)) {
+                    errorMessage = GlobalAppContext.getString(R.string.text_enable_accessibility_service_by_root_timeout)
+                }
+            } else {
+                errorMessage = GlobalAppContext.getString(R.string.text_no_accessibility_permission)
+            }
+        }
+        if (errorMessage != null) {
+            AccessibilityServiceTool.goToAccessibilitySetting()
+            if (!AccessibilityService.waitForEnabled(-1)) {
+                throw ScriptInterruptedException()
+            }
+        }
+    }
+
+    override fun initScriptEngineManager() {
+        super.initScriptEngineManager()
+        scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) {
+            val engine = XJavaScriptEngine(application)
+            engine.runtime = createRuntime()
+            engine
+        }
+    }
+
+//    override fun createRuntime(): ScriptRuntime {
+//        val runtime = super.createRuntime()
+//        runtime.putProperty("class.settings", SettingsActivity::class.java)
+//        runtime.putProperty("class.console", LogActivity::class.java)
+//        return runtime
+//    }
+
+    companion object {
+
+        @SuppressLint("StaticFieldLeak")
+        lateinit var instance: DemoAutoJs
+            private set
+
+        fun initInstance(application: Application) {
+            instance = DemoAutoJs(application)
+        }
+    }
+}

+ 95 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/GlobalKeyObserver.kt

@@ -0,0 +1,95 @@
+package com.cj.autojs.dtok.autojs
+
+import android.util.Log
+import android.view.KeyEvent
+
+import com.stardust.app.GlobalAppContext
+import com.stardust.autojs.core.inputevent.InputEventObserver
+import com.stardust.autojs.core.inputevent.ShellKeyObserver
+import com.stardust.view.accessibility.AccessibilityService
+import com.stardust.view.accessibility.OnKeyListener
+import com.cj.autojs.dtok.Pref
+
+/**
+ * Created by Stardust on 2017/8/14.
+ */
+
+class GlobalKeyObserver internal constructor() : OnKeyListener, ShellKeyObserver.KeyListener {
+    private var mVolumeDownFromShell: Boolean = false
+    private var mVolumeDownFromAccessibility: Boolean = false
+    private var mVolumeUpFromShell: Boolean = false
+    private var mVolumeUpFromAccessibility: Boolean = false
+
+    init {
+        AccessibilityService.stickOnKeyObserver
+                .addListener(this)
+        val observer = ShellKeyObserver()
+        observer.setKeyListener(this)
+        InputEventObserver.getGlobal(GlobalAppContext.get()).addListener(observer)
+    }
+
+    fun onVolumeUp() {
+        Log.d(LOG_TAG, "onVolumeUp at " + System.currentTimeMillis())
+        if (Pref.shouldStopAllScriptsWhenVolumeUp()) {
+            DemoAutoJs.instance!!.scriptEngineService.stopAllAndToast()
+        }
+    }
+
+    override fun onKeyEvent(keyCode: Int, event: KeyEvent) {
+        if (event.action != KeyEvent.ACTION_UP)
+            return
+        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+            if (mVolumeDownFromShell) {
+                mVolumeDownFromShell = false
+                return
+            }
+            mVolumeUpFromAccessibility = true
+            onVolumeDown()
+        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+            if (mVolumeUpFromShell) {
+                mVolumeUpFromShell = false
+                return
+            }
+            mVolumeUpFromAccessibility = true
+            onVolumeUp()
+        }
+    }
+
+    fun onVolumeDown() {
+
+    }
+
+
+    override fun onKeyDown(keyName: String) {
+
+    }
+
+    override fun onKeyUp(keyName: String) {
+        if ("KEY_VOLUMEUP" == keyName) {
+            if (mVolumeUpFromAccessibility) {
+                mVolumeUpFromAccessibility = false
+                return
+            }
+            mVolumeUpFromShell = true
+            onVolumeUp()
+        } else if ("KEY_VOLUMEDOWN" == keyName) {
+            if (mVolumeDownFromAccessibility) {
+                mVolumeDownFromAccessibility = false
+                return
+            }
+            mVolumeDownFromShell = true
+            onVolumeDown()
+        }
+    }
+
+    companion object {
+
+
+        private val LOG_TAG = "GlobalKeyObserver"
+        private val sSingleton = GlobalKeyObserver()
+
+        fun init() {
+            //do nothing
+        }
+    }
+}

+ 37 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/ScriptExecutionGlobalListener.kt

@@ -0,0 +1,37 @@
+package com.cj.autojs.dtok.autojs
+
+import com.stardust.app.GlobalAppContext
+import com.stardust.autojs.execution.ScriptExecution
+import com.stardust.autojs.execution.ScriptExecutionListener
+import com.cj.autojs.dtok.R
+
+/**
+ * Created by Stardust on 2017/5/3.
+ */
+
+class ScriptExecutionGlobalListener : ScriptExecutionListener {
+
+    override fun onStart(execution: ScriptExecution) {
+        execution.engine.setTag(ENGINE_TAG_START_TIME, System.currentTimeMillis())
+    }
+
+    override fun onSuccess(execution: ScriptExecution, result: Any?) {
+        onFinish(execution)
+    }
+
+    private fun onFinish(execution: ScriptExecution) {
+        val millis = execution.engine.getTag(ENGINE_TAG_START_TIME) as Long? ?: return
+        val seconds = (System.currentTimeMillis() - millis) / 1000.0
+        DemoAutoJs.instance.scriptEngineService.globalConsole
+                .verbose(GlobalAppContext.getString(R.string.text_execution_finished), execution.source.toString(), seconds)
+    }
+
+    override fun onException(execution: ScriptExecution, e: Throwable) {
+        onFinish(execution)
+    }
+
+    companion object {
+        private const val ENGINE_TAG_START_TIME = "start_time"
+    }
+
+}

+ 42 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/autojs/XJavaScriptEngine.kt

@@ -0,0 +1,42 @@
+package com.cj.autojs.dtok.autojs
+
+import android.content.Context
+import com.stardust.autojs.engine.LoopBasedJavaScriptEngine
+import com.stardust.autojs.engine.encryption.ScriptEncryption
+import com.stardust.autojs.script.EncryptedScriptFileHeader
+import com.stardust.autojs.script.JavaScriptFileSource
+import com.stardust.autojs.script.ScriptSource
+import com.stardust.autojs.script.StringScriptSource
+import com.stardust.pio.PFiles
+import java.io.File
+import java.security.GeneralSecurityException
+
+class XJavaScriptEngine(context: Context) : LoopBasedJavaScriptEngine(context) {
+    override fun execute(source: ScriptSource, callback: ExecuteCallback?) {
+        if (source is JavaScriptFileSource) {
+            try {
+                if (execute(source.file)) {
+                    return
+                }
+            } catch (e: Throwable) {
+                e.printStackTrace()
+                return
+            }
+        }
+        super.execute(source, callback)
+    }
+
+    private fun execute(file: File): Boolean {
+        val bytes = PFiles.readBytes(file.path)
+        if (!EncryptedScriptFileHeader.isValidFile(bytes)) {
+            return false
+        }
+        try {
+            super.execute(StringScriptSource(file.name, String(ScriptEncryption.decrypt(bytes, EncryptedScriptFileHeader.BLOCK_SIZE))))
+        } catch (e: GeneralSecurityException) {
+            e.printStackTrace()
+        }
+        return true
+    }
+
+}

+ 16 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/config/UrlConfig.java

@@ -0,0 +1,16 @@
+package com.cj.autojs.dtok.config;
+
+public class UrlConfig {
+
+
+    public static Boolean foreground;
+    public static String conf;
+    public static String name;
+    public static String script;
+
+    public static final String BASE_API = "https://api.ruanjian168.cc/api/";
+    public static final String UI_URL = "http://192.168.2.24:8080";
+    public static final String LOGIN_URL = "https://api.ruanjian168.cc/login";
+
+    public static final String DEVICE = "DEVICE";
+}

+ 108 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/entity/Device.java

@@ -0,0 +1,108 @@
+package com.cj.autojs.dtok.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class Device implements Serializable {
+
+    private String uuid;
+    private int account;
+    private String deviceName;
+    private String deviceVersion;
+    private String deviceBrand;
+    private Date lastConnectionTime;
+    private String tiktokVersion;
+    private String status;
+    private String androidId;
+    private String lastConnectionIp;
+    private Date registerAt;
+
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public int getAccount() {
+        return account;
+    }
+
+    public void setAccount(int account) {
+        this.account = account;
+    }
+
+    public String getDeviceName() {
+        return deviceName;
+    }
+
+    public void setDeviceName(String deviceName) {
+        this.deviceName = deviceName;
+    }
+
+    public String getDeviceVersion() {
+        return deviceVersion;
+    }
+
+    public void setDeviceVersion(String deviceVersion) {
+        this.deviceVersion = deviceVersion;
+    }
+
+    public String getDeviceBrand() {
+        return deviceBrand;
+    }
+
+    public void setDeviceBrand(String deviceBrand) {
+        this.deviceBrand = deviceBrand;
+    }
+
+    public Date getLastConnectionTime() {
+        return lastConnectionTime;
+    }
+
+    public void setLastConnectionTime(Date lastConnectionTime) {
+        this.lastConnectionTime = lastConnectionTime;
+    }
+
+    public String getTiktokVersion() {
+        return tiktokVersion;
+    }
+
+    public void setTiktokVersion(String tiktokVersion) {
+        this.tiktokVersion = tiktokVersion;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getAndroidId() {
+        return androidId;
+    }
+
+    public void setAndroidId(String androidId) {
+        this.androidId = androidId;
+    }
+
+    public String getLastConnectionIp() {
+        return lastConnectionIp;
+    }
+
+    public void setLastConnectionIp(String lastConnectionIp) {
+        this.lastConnectionIp = lastConnectionIp;
+    }
+
+    public Date getRegisterAt() {
+        return registerAt;
+    }
+
+    public void setRegisterAt(Date registerAt) {
+        this.registerAt = registerAt;
+    }
+}

+ 87 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/entity/User.java

@@ -0,0 +1,87 @@
+package com.cj.autojs.dtok.entity;
+
+
+public class User {
+    private int id;
+    private String username;
+    private int maxDevices;
+    private long phoneNumber;
+    private String name;
+    private boolean status;
+    private boolean isSuper;
+    private String expireAt;
+    private long expireTime;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+
+    public int getMaxDevices() {
+        return maxDevices;
+    }
+
+    public void setMaxDevices(int maxDevices) {
+        this.maxDevices = maxDevices;
+    }
+
+    public long getPhoneNumber() {
+        return phoneNumber;
+    }
+
+    public void setPhoneNumber(long phoneNumber) {
+        this.phoneNumber = phoneNumber;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isStatus() {
+        return status;
+    }
+
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+
+    public boolean isSuper() {
+        return isSuper;
+    }
+
+    public void setSuper(boolean aSuper) {
+        isSuper = aSuper;
+    }
+
+    public String getExpireAt() {
+        return expireAt;
+    }
+
+    public void setExpireAt(String expireAt) {
+        this.expireAt = expireAt;
+    }
+
+    public long getExpireTime() {
+        return expireTime;
+    }
+
+    public void setExpireTime(long expireTime) {
+        this.expireTime = expireTime;
+    }
+}

+ 289 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularActionMenu.java

@@ -0,0 +1,289 @@
+package com.cj.autojs.dtok.floating;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.PointF;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.Interpolator;
+import android.view.animation.ScaleAnimation;
+import android.widget.FrameLayout;
+import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
+
+import com.cj.autojs.dtok.R;
+
+import java.util.Iterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/* loaded from: classes.dex */
+public class CircularActionMenu extends FrameLayout {
+    private float mAngle;
+    private boolean mCollapsing;
+    private long mDuration;
+    private boolean mExpanded;
+    private int mExpandedHeight;
+    private int mExpandedWidth;
+    private boolean mExpanding;
+    private final Interpolator mInterpolator;
+    private PointF[] mItemExpandedPositionOffsets;
+    private CopyOnWriteArrayList<OnStateChangeListener> mOnStateChangeListeners;
+    private float mRadius;
+
+    /* loaded from: classes.dex */
+    public interface OnStateChangeListener {
+        void onCollapsed(CircularActionMenu circularActionMenu);
+
+        void onCollapsing(CircularActionMenu circularActionMenu);
+
+        void onExpanded(CircularActionMenu circularActionMenu);
+
+        void onExpanding(CircularActionMenu circularActionMenu);
+
+        void onMeasured(CircularActionMenu circularActionMenu);
+    }
+
+    /* loaded from: classes.dex */
+    public static class OnStateChangeListenerAdapter implements OnStateChangeListener {
+        @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+        public void onCollapsed(CircularActionMenu circularActionMenu) {
+        }
+
+        @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+        public void onCollapsing(CircularActionMenu circularActionMenu) {
+        }
+
+        @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+        public void onExpanded(CircularActionMenu circularActionMenu) {
+        }
+
+        @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+        public void onExpanding(CircularActionMenu circularActionMenu) {
+        }
+
+        @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+        public void onMeasured(CircularActionMenu circularActionMenu) {
+        }
+    }
+
+    public CircularActionMenu(Context context) {
+        super(context);
+        this.mOnStateChangeListeners = new CopyOnWriteArrayList<>();
+        this.mExpanding = false;
+        this.mCollapsing = false;
+        this.mRadius = 0.0f;
+        this.mAngle = (float) Math.toRadians(90.0d);
+        this.mDuration = 200L;
+        this.mExpandedHeight = -1;
+        this.mExpandedWidth = -1;
+        this.mInterpolator = new FastOutSlowInInterpolator();
+        init(null);
+    }
+
+    public CircularActionMenu(Context context, AttributeSet attributeSet) {
+        super(context, attributeSet);
+        this.mOnStateChangeListeners = new CopyOnWriteArrayList<>();
+        this.mExpanding = false;
+        this.mCollapsing = false;
+        this.mRadius = 0.0f;
+        this.mAngle = (float) Math.toRadians(90.0d);
+        this.mDuration = 200L;
+        this.mExpandedHeight = -1;
+        this.mExpandedWidth = -1;
+        this.mInterpolator = new FastOutSlowInInterpolator();
+        init(attributeSet);
+    }
+
+    public CircularActionMenu(Context context, AttributeSet attributeSet, int i) {
+        super(context, attributeSet, i);
+        this.mOnStateChangeListeners = new CopyOnWriteArrayList<>();
+        this.mExpanding = false;
+        this.mCollapsing = false;
+        this.mRadius = 0.0f;
+        this.mAngle = (float) Math.toRadians(90.0d);
+        this.mDuration = 200L;
+        this.mExpandedHeight = -1;
+        this.mExpandedWidth = -1;
+        this.mInterpolator = new FastOutSlowInInterpolator();
+        init(attributeSet);
+    }
+
+    private void init(AttributeSet attributeSet) {
+        if (attributeSet == null) {
+            return;
+        }
+        TypedArray obtainStyledAttributes = getContext().obtainStyledAttributes(attributeSet, R.styleable.CircularActionMenu);
+        this.mRadius = obtainStyledAttributes.getDimensionPixelSize(1, (int) this.mRadius);
+        int i = obtainStyledAttributes.getInt(0, 0);
+        if (i != 0) {
+            this.mAngle = (float) Math.toRadians(i);
+        }
+        for (int i2 = 0; i2 < getItemCount(); i2++) {
+            View itemAt = getItemAt(i2);
+            FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) itemAt.getLayoutParams();
+            layoutParams.gravity = 8388627;
+            updateViewLayout(itemAt, layoutParams);
+        }
+        requestLayout();
+    }
+
+    public float getRadius() {
+        return this.mRadius;
+    }
+
+    public void setRadius(float f) {
+        this.mRadius = f;
+    }
+
+    public float getAngle() {
+        return this.mAngle;
+    }
+
+    public void setAngle(float f) {
+        this.mAngle = f;
+    }
+
+    public void expand(int i) {
+        setVisibility(View.VISIBLE);
+        this.mExpanding = true;
+        AnimatorListenerAdapter animatorListenerAdapter = new AnimatorListenerAdapter() { // from class: com.phgors.auto.floating.CircularActionMenu.1
+            @Override // android.animation.AnimatorListenerAdapter, android.animation.Animator.AnimatorListener
+            public void onAnimationEnd(Animator animator) {
+                CircularActionMenu.this.mExpanding = false;
+                CircularActionMenu.this.mExpanded = true;
+                Iterator it = CircularActionMenu.this.mOnStateChangeListeners.iterator();
+                while (it.hasNext()) {
+                    ((OnStateChangeListener) it.next()).onExpanded(CircularActionMenu.this);
+                }
+            }
+        };
+        ScaleAnimation createScaleAnimation = createScaleAnimation(0.0f, 1.0f);
+        int i2 = i != 5 ? -1 : 1;
+        for (int i3 = 0; i3 < getItemCount(); i3++) {
+            View itemAt = getItemAt(i3);
+            itemAt.animate().translationXBy(i2 * this.mItemExpandedPositionOffsets[i3].x).translationYBy(this.mItemExpandedPositionOffsets[i3].y).setListener(animatorListenerAdapter).setDuration(this.mDuration).start();
+            itemAt.startAnimation(createScaleAnimation);
+        }
+        Iterator<OnStateChangeListener> it = this.mOnStateChangeListeners.iterator();
+        while (it.hasNext()) {
+            it.next().onExpanding(this);
+        }
+    }
+
+    private ScaleAnimation createScaleAnimation(float f, float f2) {
+        ScaleAnimation scaleAnimation = new ScaleAnimation(f, f2, f, f2, 1, 0.0f, 1, 0.5f);
+        scaleAnimation.setDuration(this.mDuration);
+        scaleAnimation.setFillAfter(true);
+        scaleAnimation.setInterpolator(this.mInterpolator);
+        return scaleAnimation;
+    }
+
+    public View getItemAt(int i) {
+        return getChildAt(i);
+    }
+
+    public void collapse() {
+        AnimatorListenerAdapter animatorListenerAdapter = new AnimatorListenerAdapter() { // from class: com.phgors.auto.floating.CircularActionMenu.2
+            @Override // android.animation.AnimatorListenerAdapter, android.animation.Animator.AnimatorListener
+            public void onAnimationEnd(Animator animator) {
+                CircularActionMenu.this.mCollapsing = false;
+                CircularActionMenu.this.mExpanded = false;
+                CircularActionMenu.this.setVisibility(View.GONE);
+                Iterator it = CircularActionMenu.this.mOnStateChangeListeners.iterator();
+                while (it.hasNext()) {
+                    ((OnStateChangeListener) it.next()).onCollapsed(CircularActionMenu.this);
+                }
+            }
+        };
+        this.mCollapsing = true;
+        ScaleAnimation createScaleAnimation = createScaleAnimation(1.0f, 0.0f);
+        for (int i = 0; i < getItemCount(); i++) {
+            View itemAt = getItemAt(i);
+            itemAt.animate().translationX(0.0f).translationY(0.0f).setListener(animatorListenerAdapter).setDuration(this.mDuration).setInterpolator(this.mInterpolator).start();
+            itemAt.startAnimation(createScaleAnimation);
+        }
+        Iterator<OnStateChangeListener> it = this.mOnStateChangeListeners.iterator();
+        while (it.hasNext()) {
+            it.next().onCollapsing(this);
+        }
+    }
+
+    public void addOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
+        this.mOnStateChangeListeners.add(onStateChangeListener);
+    }
+
+    public boolean removeOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
+        return this.mOnStateChangeListeners.remove(onStateChangeListener);
+    }
+
+    public boolean isExpanded() {
+        return this.mExpanded;
+    }
+
+    public boolean isExpanding() {
+        return this.mExpanding;
+    }
+
+    public boolean isCollapsing() {
+        return this.mCollapsing;
+    }
+
+    public int getItemCount() {
+        return getChildCount();
+    }
+
+    private void calcExpandedPositions() {
+        this.mItemExpandedPositionOffsets = new PointF[getItemCount()];
+        double itemCount = this.mAngle / (getItemCount() - 1);
+        for (int i = 0; i < getItemCount(); i++) {
+            double d = ((-this.mAngle) / 2.0f) + (i * itemCount);
+            this.mItemExpandedPositionOffsets[i] = new PointF((float) (this.mRadius * Math.cos(d)), (float) (this.mRadius * Math.sin(d)));
+        }
+    }
+
+    private void calcExpandedSize() {
+        int i = 0;
+        int i2 = 0;
+        int i3 = 0;
+        int i4 = Integer.MAX_VALUE;
+        for (int i5 = 0; i5 < getItemCount(); i5++) {
+            View itemAt = getItemAt(i5);
+            i3 = Math.max(itemAt.getMeasuredWidth(), i3);
+            i = Math.max((int) (this.mItemExpandedPositionOffsets[i5].x + itemAt.getMeasuredWidth()), i);
+            i2 = Math.max((int) (this.mItemExpandedPositionOffsets[i5].y + itemAt.getMeasuredHeight()), i2);
+            i4 = Math.min((int) (this.mItemExpandedPositionOffsets[i5].y - itemAt.getMeasuredHeight()), i4);
+        }
+        this.mExpandedWidth = i;
+        this.mExpandedHeight = i2 - i4;
+    }
+
+    @Override // android.widget.FrameLayout, android.view.View
+    protected void onMeasure(int i, int i2) {
+        measureChildren(i, i2);
+        calcExpandedPositions();
+        if (this.mExpandedHeight == -1 || this.mExpandedWidth == -1) {
+            calcExpandedSize();
+        }
+        setMeasuredDimension(this.mExpandedWidth * 2, this.mExpandedHeight);
+        Iterator<OnStateChangeListener> it = this.mOnStateChangeListeners.iterator();
+        while (it.hasNext()) {
+            it.next().onMeasured(this);
+        }
+    }
+
+    @Override // android.view.ViewGroup
+    protected void measureChildren(int i, int i2) {
+        for (int i3 = 0; i3 < getChildCount(); i3++) {
+            measureChild(getChildAt(i3), i, i2);
+        }
+    }
+
+    public int getExpandedHeight() {
+        return this.mExpandedHeight;
+    }
+
+    public int getExpandedWidth() {
+        return this.mExpandedWidth;
+    }
+}

+ 137 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularMenu.java

@@ -0,0 +1,137 @@
+package com.cj.autojs.dtok.floating;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+
+import com.makeramen.roundedimageview.RoundedImageView;
+import com.stardust.enhancedfloaty.FloatyService;
+import com.cj.autojs.dtok.MainActivity;
+import com.cj.autojs.dtok.R;
+import com.cj.autojs.dtok.config.UrlConfig;
+import com.cj.autojs.dtok.launch.GlobalProjectLauncher;
+
+import org.opencv.videoio.Videoio;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+import butterknife.Optional;
+
+public class CircularMenu {
+    private static final String LOG_TAG = "CircularMenu";
+    public static final long TIMEOUT_MILLS = 60000;
+    public static TimerTask timeoutTask;
+    public static Timer timer;
+    private RoundedImageView mActionViewIcon;
+    private Context mContext;
+    CircularMenuWindow mWindow;
+
+    @BindView(R.id.btnMenuStart)View btnMenuStart;
+    @BindView(R.id.btnMenuStop)View btnMenuStop;
+    @BindView(R.id.btnMenuBack)View btnMenuBack;
+    @BindView(R.id.btnMenuExit)View btnMenuExit;
+
+
+    public CircularMenu(Context context) {
+        this.mContext = new ContextThemeWrapper(context, (int) R.style.AppTheme);
+        initFloaty();
+        setupListeners();
+
+    }
+
+
+    private void setupListeners() {
+        this.mWindow.setOnActionViewClickListener(view -> {
+            if (mWindow.isExpanded()) {
+                mWindow.collapse();
+            } else {
+                mWindow.expand();
+            }
+        });
+    }
+
+
+    private void initFloaty() {
+        CircularMenuWindow circularMenuWindow = new CircularMenuWindow(this.mContext, new CircularMenuFloaty() { // from class: com.phgors.auto.floating.CircularMenu.2
+            @Override // com.phgors.auto.floating.CircularMenuFloaty
+            public View inflateActionView(FloatyService floatyService, CircularMenuWindow circularMenuWindow2) {
+                View inflate = View.inflate(floatyService, R.layout.circular_action_view, null);
+                CircularMenu.this.mActionViewIcon = (RoundedImageView) inflate.findViewById(R.id.icon);
+//                inflate.setFocusableInTouchMode(true);
+
+                return inflate;
+            }
+
+            @Override // com.phgors.auto.floating.CircularMenuFloaty
+            public CircularActionMenu inflateMenuItems(FloatyService floatyService, CircularMenuWindow circularMenuWindow2) {
+                CircularActionMenu circularActionMenu = (CircularActionMenu) View.inflate(new ContextThemeWrapper(floatyService, (int) R.style.AppTheme), R.layout.circular_action_menu, null);
+//                circularActionMenu.setFocusableInTouchMode(true);
+//                circularActionMenu.getItemAt(0).setOnClickListener(new View.OnClickListener() {
+//                    @Override
+//                    public void onClick(View view) {
+//                        Log.d("Menu", "onClick: XXXX");
+//                    }
+//                });
+//                circularActionMenu.getItemAt(1).setOnClickListener(new View.OnClickListener() {
+//                    @Override
+//                    public void onClick(View view) {
+//                        DemoAutoJs.Companion.getInstance().getUiHandler().toast("CLICK");
+//                    }
+//                });
+                ButterKnife.bind(CircularMenu.this, circularActionMenu);
+                return circularActionMenu;
+            }
+        });
+        this.mWindow = circularMenuWindow;
+        circularMenuWindow.setKeepToSideHiddenWidthRadio(0.25f);
+        FloatyService.addWindow(this.mWindow);
+    }
+
+    /* JADX INFO: Access modifiers changed from: package-private */
+    @OnClick(R.id.btnMenuStart)
+    @Optional
+    public void startScripts() {
+        this.mWindow.collapse();
+
+        GlobalProjectLauncher.INSTANCE.launch(null);
+    }
+
+    /* JADX INFO: Access modifiers changed from: package-private */
+    @OnClick({R.id.btnMenuStop})
+    @Optional
+    public void stopAllScripts() {
+        this.mWindow.collapse();
+
+        GlobalProjectLauncher.INSTANCE.Stop();
+    }
+
+    /* JADX INFO: Access modifiers changed from: package-private */
+    @OnClick({R.id.btnMenuBack})
+    @Optional
+    public void backHome() {
+        this.mWindow.collapse();
+        GlobalProjectLauncher.INSTANCE.Stop();
+//        GlobalProjectLauncher.INSTANCE.Stop();
+        this.mContext.startActivity(new Intent(this.mContext, MainActivity.class).addFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR));
+
+    }
+
+    @OnClick({R.id.btnMenuExit})
+    @Optional
+    public void close() {
+        GlobalProjectLauncher.INSTANCE.Stop();
+        UrlConfig.script = null;
+        this.mWindow.close();
+//        timer.cancel();
+//        timeoutTask.cancel();
+//        timer = null;
+//        timeoutTask = null;
+        FloatyWindowManger.sCircularMenu = null;
+
+    }
+}

+ 13 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularMenuFloaty.java

@@ -0,0 +1,13 @@
+package com.cj.autojs.dtok.floating;
+
+
+import android.view.View;
+
+import com.stardust.enhancedfloaty.FloatyService;
+
+/* loaded from: classes.dex */
+public interface CircularMenuFloaty {
+    View inflateActionView(FloatyService floatyService, CircularMenuWindow circularMenuWindow);
+
+    CircularActionMenu inflateMenuItems(FloatyService floatyService, CircularMenuWindow circularMenuWindow);
+}

+ 231 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/CircularMenuWindow.java

@@ -0,0 +1,231 @@
+package com.cj.autojs.dtok.floating;
+
+import android.content.Context;
+import android.preference.PreferenceManager;
+import android.view.OrientationEventListener;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.stardust.autojs.core.inputevent.InputEventCodes;
+import com.stardust.enhancedfloaty.FloatyService;
+import com.stardust.enhancedfloaty.FloatyWindow;
+import com.stardust.enhancedfloaty.WindowBridge;
+import com.stardust.util.ScreenMetrics;
+import com.cj.autojs.dtok.floating.gesture.BounceDragGesture;
+
+/* loaded from: classes.dex */
+public class CircularMenuWindow extends FloatyWindow {
+    public static final String KEY_POSITION_X = CircularMenuWindow.class.getName() + ".position.x";
+    public static final String KEY_POSITION_Y = CircularMenuWindow.class.getName() + ".position.y";
+    protected View.OnClickListener mActionViewOnClickListener;
+    protected OrientationAwareWindowBridge mActionViewWindowBridge;
+    protected WindowManager.LayoutParams mActionViewWindowLayoutParams;
+    protected CircularActionMenu mCircularActionMenu;
+    protected View mCircularActionView;
+    private Context mContext;
+    protected BounceDragGesture mDragGesture;
+    protected CircularMenuFloaty mFloaty;
+    protected float mKeepToSideHiddenWidthRadio;
+    protected WindowBridge mMenuWindowBridge;
+    protected WindowManager.LayoutParams mMenuWindowLayoutParams;
+    private OrientationEventListener mOrientationEventListener;
+    protected float mActiveAlpha = 1.0f;
+    protected float mInactiveAlpha = 0.5f;
+
+    @Override // com.stardust.enhancedfloaty.FloatyWindow
+    protected View onCreateView(FloatyService floatyService) {
+        return null;
+    }
+
+    @Override // com.stardust.enhancedfloaty.FloatyWindow
+    protected WindowManager.LayoutParams onCreateWindowLayoutParams() {
+        return null;
+    }
+
+    public CircularMenuWindow(Context context, CircularMenuFloaty circularMenuFloaty) {
+        this.mFloaty = circularMenuFloaty;
+        this.mContext = context;
+    }
+
+    @Override // com.stardust.enhancedfloaty.FloatyWindow
+    protected void onCreateWindow(FloatyService floatyService, WindowManager windowManager) {
+        this.mActionViewWindowLayoutParams = createWindowLayoutParams();
+        this.mMenuWindowLayoutParams = createWindowLayoutParams();
+        inflateWindowViews(floatyService);
+        initWindowBridge();
+        initGestures();
+        setListeners();
+        setInitialState();
+        OrientationEventListener orientationEventListener = new OrientationEventListener(this.mContext) { // from class: com.phgors.auto.floating.CircularMenuWindow.1
+            @Override // android.view.OrientationEventListener
+            public void onOrientationChanged(int i) {
+                if (CircularMenuWindow.this.mActionViewWindowBridge.isOrientationChanged(CircularMenuWindow.this.mContext.getResources().getConfiguration().orientation)) {
+                    CircularMenuWindow.this.keepToSide();
+                }
+            }
+        };
+        this.mOrientationEventListener = orientationEventListener;
+        if (orientationEventListener.canDetectOrientation()) {
+            this.mOrientationEventListener.enable();
+        }
+    }
+
+    /* JADX INFO: Access modifiers changed from: private */
+    public void keepToSide() {
+        this.mDragGesture.keepToEdge();
+    }
+
+    private void setInitialState() {
+        int i = PreferenceManager.getDefaultSharedPreferences(this.mContext).getInt(KEY_POSITION_Y, ScreenMetrics.getDeviceScreenHeight() / 4);
+        OrientationAwareWindowBridge orientationAwareWindowBridge = this.mActionViewWindowBridge;
+        orientationAwareWindowBridge.updatePosition(orientationAwareWindowBridge.getX(), i);
+        keepToSide();
+    }
+
+    private void initGestures() {
+        BounceDragGesture bounceDragGesture = new BounceDragGesture(this.mActionViewWindowBridge, this.mCircularActionView);
+        this.mDragGesture = bounceDragGesture;
+        bounceDragGesture.setKeepToSideHiddenWidthRadio(this.mKeepToSideHiddenWidthRadio);
+        this.mDragGesture.setPressedAlpha(this.mActiveAlpha);
+        this.mDragGesture.setUnpressedAlpha(this.mInactiveAlpha);
+    }
+
+    private void initWindowBridge() {
+        this.mActionViewWindowBridge = new OrientationAwareWindowBridge(this.mActionViewWindowLayoutParams, getWindowManager(), this.mCircularActionView, this.mContext);
+        this.mMenuWindowBridge = new WindowBridge.DefaultImpl(this.mMenuWindowLayoutParams, getWindowManager(), this.mCircularActionMenu);
+    }
+
+    public void setKeepToSideHiddenWidthRadio(float f) {
+        this.mKeepToSideHiddenWidthRadio = f;
+        BounceDragGesture bounceDragGesture = this.mDragGesture;
+        if (bounceDragGesture != null) {
+            bounceDragGesture.setKeepToSideHiddenWidthRadio(f);
+        }
+    }
+
+    private WindowManager.LayoutParams createWindowLayoutParams() {
+        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(-2, -2, FloatyWindowManger.getWindowType(), InputEventCodes.KEY_NUMERIC_8, -3);
+        layoutParams.gravity = 51;
+        return layoutParams;
+    }
+
+    private void setListeners() {
+        setOnActionViewClickListener(new View.OnClickListener() { // from class: com.phgors.auto.floating.CircularMenuWindow$$ExternalSyntheticLambda0
+            @Override // android.view.View.OnClickListener
+            public final void onClick(View view) {
+                CircularMenuWindow.this.m32xde642159(view);
+            }
+        });
+        View.OnClickListener onClickListener = this.mActionViewOnClickListener;
+        if (onClickListener != null) {
+            this.mDragGesture.setOnDraggedViewClickListener(onClickListener);
+        }
+        this.mCircularActionMenu.addOnStateChangeListener(new CircularActionMenu.OnStateChangeListenerAdapter() { // from class: com.phgors.auto.floating.CircularMenuWindow.2
+            @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListenerAdapter, com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+            public void onCollapsed(CircularActionMenu circularActionMenu) {
+                CircularMenuWindow.this.mCircularActionView.setAlpha(CircularMenuWindow.this.mInactiveAlpha);
+            }
+
+            @Override // com.phgors.auto.floating.CircularActionMenu.OnStateChangeListenerAdapter, com.phgors.auto.floating.CircularActionMenu.OnStateChangeListener
+            public void onExpanded(CircularActionMenu circularActionMenu) {
+                CircularMenuWindow.this.mCircularActionView.setAlpha(CircularMenuWindow.this.mActiveAlpha);
+            }
+        });
+    }
+
+    /* JADX INFO: Access modifiers changed from: package-private */
+    /* renamed from: lambda$setListeners$0$com-phgors-auto-floating-CircularMenuWindow  reason: not valid java name */
+    public /* synthetic */ void m32xde642159(View view) {
+        if (isExpanded()) {
+            collapse();
+        } else {
+            expand();
+        }
+    }
+
+    public void setOnActionViewClickListener(View.OnClickListener onClickListener) {
+        BounceDragGesture bounceDragGesture = this.mDragGesture;
+        if (bounceDragGesture == null) {
+            this.mActionViewOnClickListener = onClickListener;
+        } else {
+            bounceDragGesture.setOnDraggedViewClickListener(onClickListener);
+        }
+    }
+
+    public void expand() {
+        this.mDragGesture.setEnabled(false);
+        setMenuPositionAtActionView();
+        if (this.mActionViewWindowBridge.getX() > this.mActionViewWindowBridge.getScreenWidth() / 2) {
+            this.mCircularActionMenu.expand(3);
+        } else {
+            this.mCircularActionMenu.expand(5);
+        }
+    }
+
+    public void setActiveAlpha(float f) {
+        this.mActiveAlpha = f;
+        BounceDragGesture bounceDragGesture = this.mDragGesture;
+        if (bounceDragGesture != null) {
+            bounceDragGesture.setPressedAlpha(f);
+        }
+    }
+
+    public void setInactiveAlpha(float f) {
+        this.mInactiveAlpha = f;
+        BounceDragGesture bounceDragGesture = this.mDragGesture;
+        if (bounceDragGesture != null) {
+            bounceDragGesture.setUnpressedAlpha(f);
+        }
+    }
+
+    public void collapse() {
+        this.mDragGesture.setEnabled(true);
+        setMenuPositionAtActionView();
+        this.mCircularActionMenu.collapse();
+        this.mCircularActionView.setAlpha(this.mDragGesture.getUnpressedAlpha());
+    }
+
+    public boolean isExpanded() {
+        return this.mCircularActionMenu.isExpanded();
+    }
+
+    private void setMenuPositionAtActionView() {
+        int x;
+        int measuredWidth;
+        int y = (this.mActionViewWindowBridge.getY() - (this.mCircularActionMenu.getMeasuredHeight() / 2)) + (this.mCircularActionView.getMeasuredHeight() / 2);
+        if (this.mActionViewWindowBridge.getX() > this.mActionViewWindowBridge.getScreenWidth() / 2) {
+            x = this.mActionViewWindowBridge.getX() - this.mCircularActionMenu.getExpandedWidth();
+            measuredWidth = this.mCircularActionView.getMeasuredWidth() / 2;
+        } else {
+            x = this.mActionViewWindowBridge.getX() - this.mCircularActionMenu.getExpandedWidth();
+            measuredWidth = this.mCircularActionView.getMeasuredWidth();
+        }
+        this.mMenuWindowBridge.updatePosition(x + measuredWidth, y);
+    }
+
+    private void inflateWindowViews(FloatyService floatyService) {
+        this.mCircularActionMenu = this.mFloaty.inflateMenuItems(floatyService, this);
+        this.mCircularActionView = this.mFloaty.inflateActionView(floatyService, this);
+        this.mCircularActionMenu.setVisibility(8);
+        getWindowManager().addView(this.mCircularActionMenu, this.mActionViewWindowLayoutParams);
+        getWindowManager().addView(this.mCircularActionView, this.mMenuWindowLayoutParams);
+    }
+
+    @Override // com.stardust.enhancedfloaty.FloatyWindow
+    public void onServiceDestroy(FloatyService floatyService) {
+        close();
+    }
+
+    @Override // com.stardust.enhancedfloaty.FloatyWindow
+    public void close() {
+        PreferenceManager.getDefaultSharedPreferences(this.mContext).edit().putInt(KEY_POSITION_X, this.mActionViewWindowBridge.getX()).putInt(KEY_POSITION_Y, this.mActionViewWindowBridge.getY()).apply();
+        try {
+            this.mOrientationEventListener.disable();
+            getWindowManager().removeView(this.mCircularActionMenu);
+            getWindowManager().removeView(this.mCircularActionView);
+            FloatyService.removeWindow(this);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 82 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/FloatyWindowManger.java

@@ -0,0 +1,82 @@
+package com.cj.autojs.dtok.floating;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.util.Log;
+import android.widget.Toast;
+import com.stardust.app.GlobalAppContext;
+import com.stardust.autojs.util.FloatingPermission;
+import com.stardust.enhancedfloaty.FloatyService;
+import com.stardust.enhancedfloaty.FloatyWindow;
+import com.cj.autojs.dtok.R;
+
+import java.lang.ref.WeakReference;
+
+/* loaded from: classes.dex */
+public class FloatyWindowManger {
+    public static WeakReference<CircularMenu> sCircularMenu;
+
+    public static boolean addWindow(Context context, FloatyWindow floatyWindow) {
+        context.startService(new Intent(context, FloatyService.class));
+        boolean ensurePermissionGranted = FloatingPermission.ensurePermissionGranted(context);
+        try {
+            FloatyService.addWindow(floatyWindow);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            if (ensurePermissionGranted) {
+                FloatingPermission.manageDrawOverlays(context);
+                GlobalAppContext.toast((int) R.string.text_no_floating_window_permission);
+                return false;
+            }
+            return false;
+        }
+    }
+
+    public static boolean isCircularMenuShowing() {
+        WeakReference<CircularMenu> weakReference = sCircularMenu;
+        return (weakReference == null || weakReference.get() == null) ? false : true;
+    }
+
+    @SuppressLint("LongLogTag")
+    public static void showCircularMenuIfNeeded() {
+        Log.d("showCircularMenuIfNeeded", "1" + sCircularMenu);
+        if (isCircularMenuShowing()) {
+//            Log.d("showCircularMenuIfNeeded", BuildConfig.AGENT_USER_ID);
+            return;
+        }
+        Log.d("showCircularMenuIfNeeded", "3");
+        showCircularMenu();
+    }
+
+    public static void showCircularMenu() {
+        if (!FloatingPermission.canDrawOverlays(GlobalAppContext.get())) {
+            Toast.makeText(GlobalAppContext.get(), (int) R.string.text_no_floating_window_permission, 0).show();
+            FloatingPermission.manageDrawOverlays(GlobalAppContext.get());
+            return;
+        }
+        GlobalAppContext.get().startService(new Intent(GlobalAppContext.get(), FloatyService.class));
+        sCircularMenu = new WeakReference<>(new CircularMenu(GlobalAppContext.get()));
+    }
+
+    @SuppressLint("LongLogTag")
+    public static void hideCircularMenu() {
+        Log.d("showCircularMenuIfNeeded", "4" + sCircularMenu);
+        WeakReference<CircularMenu> weakReference = sCircularMenu;
+        if (weakReference == null) {
+            return;
+        }
+        CircularMenu circularMenu = weakReference.get();
+        if (circularMenu != null) {
+            circularMenu.close();
+        }
+        sCircularMenu = null;
+        Log.d("showCircularMenuIfNeeded", "5" + sCircularMenu);
+    }
+
+    public static int getWindowType() {
+        return Build.VERSION.SDK_INT >= 26 ? 2038 : 2003;
+    }
+}

+ 43 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/OrientationAwareWindowBridge.java

@@ -0,0 +1,43 @@
+package com.cj.autojs.dtok.floating;
+
+import android.content.Context;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.stardust.enhancedfloaty.WindowBridge;
+
+/* loaded from: classes.dex */
+public class OrientationAwareWindowBridge extends WindowBridge.DefaultImpl {
+    private Context mContext;
+    private int mOrientation;
+
+    public OrientationAwareWindowBridge(WindowManager.LayoutParams layoutParams, WindowManager windowManager, View view, Context context) {
+        super(layoutParams, windowManager, view);
+        this.mContext = context;
+        this.mOrientation = context.getResources().getConfiguration().orientation;
+    }
+
+    public boolean isOrientationChanged(int i) {
+        if (this.mOrientation != i) {
+            this.mOrientation = i;
+            return true;
+        }
+        return false;
+    }
+
+    @Override // com.stardust.enhancedfloaty.WindowBridge.DefaultImpl, com.stardust.enhancedfloaty.WindowBridge
+    public int getScreenHeight() {
+        if (this.mContext.getResources().getConfiguration().orientation == 2) {
+            return super.getScreenWidth();
+        }
+        return super.getScreenHeight();
+    }
+
+    @Override // com.stardust.enhancedfloaty.WindowBridge.DefaultImpl, com.stardust.enhancedfloaty.WindowBridge
+    public int getScreenWidth() {
+        if (this.mContext.getResources().getConfiguration().orientation == 2) {
+            return super.getScreenHeight();
+        }
+        return super.getScreenWidth();
+    }
+}

+ 56 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/gesture/BounceDragGesture.java

@@ -0,0 +1,56 @@
+package com.cj.autojs.dtok.floating.gesture;
+
+import android.animation.ValueAnimator;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.BounceInterpolator;
+import com.stardust.enhancedfloaty.WindowBridge;
+
+/* loaded from: classes.dex */
+public class BounceDragGesture extends DragGesture {
+    private static final int MIN_DY_TO_SCREEN_BOTTOM = 100;
+    private static final int MIN_DY_TO_SCREEN_TOP = 0;
+    private long mBounceDuration;
+    private BounceInterpolator mBounceInterpolator;
+
+    public BounceDragGesture(WindowBridge windowBridge, View view) {
+        super(windowBridge, view);
+        this.mBounceDuration = 300L;
+        setAutoKeepToEdge(true);
+        this.mBounceInterpolator = new BounceInterpolator();
+    }
+
+    public void setBounceDuration(long j) {
+        this.mBounceDuration = j;
+    }
+
+    @Override // com.phgors.auto.floating.gesture.DragGesture, android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnGestureListener
+    public boolean onDown(MotionEvent motionEvent) {
+        return super.onDown(motionEvent);
+    }
+
+    @Override // com.phgors.auto.floating.gesture.DragGesture
+    public void keepToEdge() {
+        int min = Math.min((this.mWindowBridge.getScreenHeight() - this.mView.getHeight()) - 100, Math.max(0, this.mWindowBridge.getY()));
+        int x = this.mWindowBridge.getX();
+        int keepToSideHiddenWidthRadio = (int) (getKeepToSideHiddenWidthRadio() * this.mView.getWidth());
+        if (x > this.mWindowBridge.getScreenWidth() / 2) {
+            bounce(x, (this.mWindowBridge.getScreenWidth() - this.mView.getWidth()) + keepToSideHiddenWidthRadio, min);
+        } else {
+            bounce(x, -keepToSideHiddenWidthRadio, min);
+        }
+    }
+
+    protected void bounce(int i, int i2, final int i3) {
+        ValueAnimator ofFloat = ValueAnimator.ofFloat(i, i2);
+        ofFloat.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { // from class: com.phgors.auto.floating.gesture.BounceDragGesture.1
+            @Override // android.animation.ValueAnimator.AnimatorUpdateListener
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                BounceDragGesture.this.mWindowBridge.updatePosition((int) ((Float) valueAnimator.getAnimatedValue()).floatValue(), i3);
+            }
+        });
+        ofFloat.setDuration(this.mBounceDuration);
+        ofFloat.setInterpolator(this.mBounceInterpolator);
+        ofFloat.start();
+    }
+}

+ 140 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/floating/gesture/DragGesture.java

@@ -0,0 +1,140 @@
+package com.cj.autojs.dtok.floating.gesture;
+
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import androidx.core.view.GestureDetectorCompat;
+import com.stardust.app.GlobalAppContext;
+import com.stardust.enhancedfloaty.WindowBridge;
+import com.cj.autojs.dtok.floating.CircularMenuWindow;
+
+/* loaded from: classes.dex */
+public class DragGesture extends GestureDetector.SimpleOnGestureListener {
+    private boolean mAutoKeepToEdge;
+    private float mInitialTouchX;
+    private float mInitialTouchY;
+    private int mInitialX;
+    private int mInitialY;
+    private View.OnClickListener mOnClickListener;
+    protected View mView;
+    protected WindowBridge mWindowBridge;
+    private float mKeepToSideHiddenWidthRadio = 0.5f;
+    private float mPressedAlpha = 1.0f;
+    private float mUnpressedAlpha = 0.4f;
+    private boolean mEnabled = true;
+
+    public DragGesture(WindowBridge windowBridge, View view) {
+        this.mWindowBridge = windowBridge;
+        this.mView = view;
+        setupView();
+    }
+
+    private void setupView() {
+        final GestureDetectorCompat gestureDetectorCompat = new GestureDetectorCompat(this.mView.getContext(), this);
+        this.mView.setOnTouchListener(new View.OnTouchListener() { // from class: com.phgors.auto.floating.gesture.DragGesture.1
+            @Override // android.view.View.OnTouchListener
+            public boolean onTouch(View view, MotionEvent motionEvent) {
+                gestureDetectorCompat.onTouchEvent(motionEvent);
+                if (motionEvent.getAction() == 1) {
+                    DragGesture.this.mView.setAlpha(DragGesture.this.mUnpressedAlpha);
+                    if (!DragGesture.this.onTheEdge() && DragGesture.this.mAutoKeepToEdge) {
+                        DragGesture.this.keepToEdge();
+                    }
+                    PreferenceManager.getDefaultSharedPreferences(GlobalAppContext.get()).edit().putInt(CircularMenuWindow.KEY_POSITION_X, DragGesture.this.mWindowBridge.getX()).putInt(CircularMenuWindow.KEY_POSITION_Y, DragGesture.this.mWindowBridge.getY()).apply();
+                }
+                return true;
+            }
+        });
+    }
+
+    public boolean isEnabled() {
+        return this.mEnabled;
+    }
+
+    public void setEnabled(boolean z) {
+        this.mEnabled = z;
+    }
+
+    protected boolean onTheEdge() {
+        return Math.min(Math.abs(this.mWindowBridge.getX()), Math.abs(this.mWindowBridge.getX() - this.mWindowBridge.getScreenWidth())) < 5;
+    }
+
+    public float getPressedAlpha() {
+        return this.mPressedAlpha;
+    }
+
+    public void setPressedAlpha(float f) {
+        this.mPressedAlpha = f;
+    }
+
+    public float getUnpressedAlpha() {
+        return this.mUnpressedAlpha;
+    }
+
+    public void setUnpressedAlpha(float f) {
+        this.mUnpressedAlpha = f;
+    }
+
+    public void setAutoKeepToEdge(boolean z) {
+        this.mAutoKeepToEdge = z;
+    }
+
+    public boolean isAutoKeepToEdge() {
+        return this.mAutoKeepToEdge;
+    }
+
+    public void setKeepToSideHiddenWidthRadio(float f) {
+        this.mKeepToSideHiddenWidthRadio = f;
+    }
+
+    public float getKeepToSideHiddenWidthRadio() {
+        return this.mKeepToSideHiddenWidthRadio;
+    }
+
+    @Override // android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnGestureListener
+    public boolean onDown(MotionEvent motionEvent) {
+        this.mInitialX = this.mWindowBridge.getX();
+        this.mInitialY = this.mWindowBridge.getY();
+        this.mInitialTouchX = motionEvent.getRawX();
+        this.mInitialTouchY = motionEvent.getRawY();
+        return false;
+    }
+
+    @Override // android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnGestureListener
+    public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) {
+        if (this.mEnabled) {
+            this.mWindowBridge.updatePosition(this.mInitialX + ((int) (motionEvent2.getRawX() - this.mInitialTouchX)), this.mInitialY + ((int) (motionEvent2.getRawY() - this.mInitialTouchY)));
+            this.mView.setAlpha(this.mPressedAlpha);
+            Log.d("DragGesture", "onScroll");
+            return false;
+        }
+        return false;
+    }
+
+    public void keepToEdge() {
+        int x = this.mWindowBridge.getX();
+        int width = (int) (this.mKeepToSideHiddenWidthRadio * this.mView.getWidth());
+        if (x > this.mWindowBridge.getScreenWidth() / 2) {
+            WindowBridge windowBridge = this.mWindowBridge;
+            windowBridge.updatePosition((windowBridge.getScreenWidth() - this.mView.getWidth()) + width, this.mWindowBridge.getY());
+            return;
+        }
+        WindowBridge windowBridge2 = this.mWindowBridge;
+        windowBridge2.updatePosition(-width, windowBridge2.getY());
+    }
+
+    @Override // android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnDoubleTapListener
+    public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
+        View.OnClickListener onClickListener = this.mOnClickListener;
+        if (onClickListener != null) {
+            onClickListener.onClick(this.mView);
+        }
+        return super.onSingleTapConfirmed(motionEvent);
+    }
+
+    public void setOnDraggedViewClickListener(View.OnClickListener onClickListener) {
+        this.mOnClickListener = onClickListener;
+    }
+}

+ 342 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/jsinterface/JsInterface.java

@@ -0,0 +1,342 @@
+package com.cj.autojs.dtok.jsinterface;
+
+import static androidx.core.content.ContextCompat.getSystemService;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.webkit.JavascriptInterface;
+import android.webkit.WebView;
+import android.widget.Toast;
+
+import com.cj.autojs.dtok.MainActivity;
+import com.cj.autojs.dtok.MainActivity;
+import com.stardust.app.GlobalAppContext;
+import com.cj.autojs.dtok.Api;
+import com.cj.autojs.dtok.App;
+import com.cj.autojs.dtok.LoginActivity;
+import com.cj.autojs.dtok.MainActivity;
+import com.cj.autojs.dtok.config.UrlConfig;
+import com.cj.autojs.dtok.floating.FloatyWindowManger;
+import com.cj.autojs.dtok.service.ForegroundService;
+import com.cj.autojs.dtok.util.DeviceUtil;
+import com.cj.autojs.dtok.util.SharedPreferencesUtils;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.Map;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Response;
+
+
+public class JsInterface {
+
+    private Context context;
+    private WebView webView;
+
+
+    public JsInterface(Context context, WebView webView) {
+        this.context = context;
+        this.webView = webView;
+    }
+
+    /**
+     * js要调用的安卓的无参方法
+     */
+    @JavascriptInterface
+    public void jsCallAndroidMoth() {
+//        String str1 = DeviceUtil.getPhoneModel();
+//        String str2 = DeviceUtil.getPhoneBrand();
+//        String str4 = DeviceUtil.getBuildVersion();
+//        int str3 = DeviceUtil.getAppVersion(context, "com.ss.android.ugc.aweme");
+//
+//        Toast.makeText(context, str1 + str2 + str4, Toast.LENGTH_SHORT).show();
+    }
+
+    //    @JavascriptInterface
+//    public void hello(String a,String callbackId) {
+//        Toast.makeText(context,a, Toast.LENGTH_SHORT).show();
+//        webView.sendResponse(a,callbackId);
+//    }
+//
+    @JavascriptInterface
+    public String getUserInfo() {
+        Map<String, Object> map = SharedPreferencesUtils.getUserInfo(context);
+        JSONObject obj = new JSONObject(map);
+        return obj.toString();
+    }
+
+
+    @JavascriptInterface
+    public String getImei() {
+        return DeviceUtil.getDeviceIMEI(context);
+    }
+
+    @JavascriptInterface
+    public String getPhoneModel() {
+        return DeviceUtil.getPhoneModel();
+    }
+
+    @JavascriptInterface
+    public String getBuildVersion() {
+        return DeviceUtil.getBuildVersion();
+    }
+
+    @JavascriptInterface
+    public String getPhoneBrand() {
+        return DeviceUtil.getPhoneBrand();
+    }
+
+    public void startAppWithPackageName(Context context, String packageName) {
+        //根据包名获取启动首页的intent 这个intent有可能为空
+        Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
+        if (intent != null) {
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(intent);
+        }
+    }
+
+    @JavascriptInterface
+    public final void webIsHome(boolean z) {
+        ((MainActivity) this.context).setHome(z);
+    }
+
+
+    @JavascriptInterface
+    public void setScript(String uuid, String module, String cfg) {
+        if (!((MainActivity) context).checkDrawOverlay()) {
+            ((MainActivity) context).requestWindowPermission();
+        } else if (!((MainActivity) context).checkAccessibility()) {
+            ((MainActivity) context).openDialogAccessibility();
+        } else {
+            Api.INSTANCE.getScript(uuid, module, new Callback() {
+                @Override
+                public void onFailure(Call call, IOException e) {
+
+                }
+
+                @Override
+                public void onResponse(Call call, Response response) throws IOException {
+                    if (response.body() != null) {
+                        String json = response.body().string();
+                        try {
+
+                            JSONObject scriptObj = new JSONObject(json);
+                            String message = scriptObj.getString("message");
+                            if (scriptObj.getBoolean("success")) {
+                                JSONObject script = scriptObj.getJSONObject("data");
+                                UrlConfig.script = script.getString("scriptContent");
+                                UrlConfig.name = script.getString("module");
+                                UrlConfig.conf = cfg;
+                                ((Activity) context).runOnUiThread(() -> {
+                                    FloatyWindowManger.showCircularMenuIfNeeded();
+                                });
+                                GlobalAppContext.toast("当前任务:" + UrlConfig.name);
+                                startAppWithPackageName(context, "com.ss.android.ugc.aweme");
+                            } else {
+                                ((Activity) context).runOnUiThread(() -> {
+                                    Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+                                });
+                            }
+                        } catch (JSONException e) {
+                            throw new RuntimeException(e);
+                        }
+
+                    }
+                }
+            });
+        }
+
+
+    }
+
+    @JavascriptInterface
+    public final void setForeground(boolean z) {
+        UrlConfig.foreground = false;
+        if (z) {
+            ForegroundService.start(GlobalAppContext.get());
+        } else {
+            ForegroundService.stop(GlobalAppContext.get());
+        }
+    }
+
+    @JavascriptInterface
+    public final boolean isOpenNotify(boolean z) {
+        return ((MainActivity) context).isNotificationEnabled();
+    }
+
+    @JavascriptInterface
+    public final boolean isAccessibility(boolean z) {
+        return ((MainActivity) context).checkAccessibility();
+    }
+
+    @JavascriptInterface
+    public final boolean isFloaty(boolean z) {
+        return ((MainActivity) context).checkDrawOverlay();
+    }
+
+    @JavascriptInterface
+    public final void OpenNotify(boolean z) {
+        ((MainActivity) context).jumpNotificationSetting();
+    }
+
+    @JavascriptInterface
+    public final void openAccessibility(boolean z) {
+        ((MainActivity) context).openAccessibility();
+    }
+
+    @JavascriptInterface
+    public final void openFloaty(boolean z) {
+        ((MainActivity) context).requestWindowPermission();
+    }
+
+
+//
+//
+//    @JavascriptInterface
+//    public void registerDevice(String param,String callbackId) {
+//        new Thread(() -> Api.INSTANCE.registerDevice(DeviceUtil.getPhoneModel(), DeviceUtil.getBuildVersion(),
+//                DeviceUtil.getPhoneBrand(), DeviceUtil.getDeviceIMEI(context), new Callback() {
+//                    @Override
+//                    public void onFailure(Call call, IOException e) {
+//                        webView.sendResponse(null,callbackId);
+//                    }
+//
+//                    @Override
+//                    public void onResponse(Call call, Response response) throws IOException {
+//                        try {
+//                            JSONObject responseData = new JSONObject(response.body().string());
+//                            if (responseData.getBoolean("success")) {
+//                                String deviceJson = responseData.getJSONObject("data").toString();
+//                                SharedPreferencesUtils.saveString(context, "registerInfo", deviceJson);
+//                                webView.sendResponse(responseData.toString(),callbackId);
+//                            } else {
+//                                webView.sendResponse(responseData.toString(),callbackId);
+//                            }
+//                        } catch (JSONException e) {
+//                            webView.sendResponse(null,callbackId);
+//                        }
+//                    }
+//                })).start();
+//    }
+//
+//
+//    @JavascriptInterface
+//    public void unBundleDevice(String param,String callbackId) {
+//        Device device = new Gson().fromJson(SharedPreferencesUtils.getString(context, "registerInfo", null), Device.class);
+//        new Thread(() -> Api.INSTANCE.unBundleDevice(device.getUuid(), new Callback() {
+//            @Override
+//            public void onFailure(Call call, IOException e) {
+//                webView.sendResponse(null,callbackId);
+//            }
+//
+//            @Override
+//            public void onResponse(Call call, Response response) throws IOException {
+//                try {
+//                    JSONObject responseData = new JSONObject(response.body().string());
+//                    if (responseData.getBoolean("success")) {
+//                        SharedPreferencesUtils.remove(context, "registerInfo");
+//                        webView.sendResponse(responseData.toString(),callbackId);
+//                    } else {
+//                        webView.sendResponse(responseData.toString(),callbackId);
+//                    }
+//                } catch (JSONException e) {
+//                    webView.sendResponse(null,callbackId);
+//                }
+//            }
+//        })).start();
+//    }
+//
+//    @JavascriptInterface
+//    public void getCommonItem(String param,String callbackId) {
+//        new Thread(() -> Api.INSTANCE.getCommonItem(new Callback() {
+//            @Override
+//            public void onFailure(Call call, IOException e) {
+//                webView.sendResponse(null,callbackId);
+//            }
+//
+//            @Override
+//            public void onResponse(Call call, Response response) throws IOException {
+//                try {
+//                    JSONObject responseData = new JSONObject(response.body().string());
+//                    webView.sendResponse(responseData.toString(),callbackId);
+//                } catch (JSONException e) {
+//                    webView.sendResponse(null,callbackId);
+//                }
+//            }
+//        })).start();
+//    }
+
+    @JavascriptInterface
+    public void reload() {
+        ((Activity) context).runOnUiThread(() -> {
+            webView.reload();
+        });
+    }
+
+    @JavascriptInterface
+    public void logout() {
+        Api.INSTANCE.setToken("");
+        Api.INSTANCE.setName("");
+        Api.INSTANCE.setExpireAt(0L);
+        SharedPreferencesUtils.remove(context, "registerInfo");
+        SharedPreferencesUtils.removeUserInfo(context);
+        SharedPreferencesUtils.remove(context, "token");
+        Intent i = new Intent(App.INSTANCE.getMContext(), LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(i);
+    }
+
+
+    @JavascriptInterface
+    public String getToken() {
+//        callbackJs(SharedPreferencesUtils.getString(context, "token", null));
+        return SharedPreferencesUtils.getString(context, "token", null);
+    }
+
+//    @JavascriptInterface
+//    public String getUserInfo() {
+////        callbackJs(SharedPreferencesUtils.getString(context, "token", null));
+//        return SharedPreferencesUtils.getString(context, "userInfo", null);
+//    }
+
+
+//
+//    /**
+//     * js要调用的安卓的有参方法
+//     */
+//    @JavascriptInterface
+//    public void jsCallAndroidMoth2(String string) {
+//        Toast.makeText(context, string, Toast.LENGTH_SHORT).show();
+//    }
+
+    /**
+     * js要调用的安卓的方法,获得数据,然后把数据回传给js
+     */
+//    @JavascriptInterface
+//    public void getData(String jsMothName) {
+//        //模拟去网上获得数据
+//        String string = "网络数据";
+//        //回调js的方法。
+//        callbackJs(jsMothName, string);
+//    }
+//
+//    /**
+//     * android 回调js,并向js传数据。
+//     */
+//    private void callbackJs(String data) {
+//        //调用js的方法必须在ui线程中运行。
+//        ((Activity) context).runOnUiThread(() -> {
+//            callbackJs(data);
+//        });
+//    }
+
+//    @Override
+//    public String send(String data) {
+//        return "it is default response";
+//    }
+}

+ 157 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/launch/AssetsProjectLauncher.kt

@@ -0,0 +1,157 @@
+package com.cj.autojs.dtok.launch
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.os.Handler
+import android.os.Looper
+import android.text.TextUtils
+import com.stardust.autojs.engine.encryption.ScriptEncryption
+import com.stardust.autojs.execution.ExecutionConfig
+import com.stardust.autojs.execution.ScriptExecution
+import com.stardust.autojs.project.ProjectConfig
+import com.stardust.autojs.script.JavaScriptSource
+import com.stardust.autojs.script.StringScriptSource
+import com.stardust.pio.PFiles
+import com.stardust.pio.UncheckedIOException
+import com.stardust.util.MD5
+import com.stardust.util.UiHandler
+import com.cj.autojs.dtok.autojs.DemoAutoJs
+import com.cj.autojs.dtok.config.UrlConfig
+import net.lingala.zip4j.util.InternalZipConstants
+import java.io.File
+import java.io.IOException
+import kotlin.jvm.internal.Intrinsics
+
+
+/**
+ * Created by Stardust on 2018/1/24.
+ */
+
+open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private val mActivity: Context?) {
+    private val mProjectDir: String = File(mActivity?.filesDir, InternalZipConstants.ZIP_FILE_SEPARATOR).path
+
+    private val mProjectConfig: ProjectConfig = ProjectConfig.fromAssets(mActivity, ProjectConfig.configFileOfDir(mAssetsProjectDir))
+    private val mMainScriptFile: File = File(mProjectDir, mProjectConfig.mainScriptFile)
+    private val mHandler: Handler = Handler(Looper.getMainLooper())
+    private var mScriptExecution: ScriptExecution? = null
+
+    init {
+        prepare()
+    }
+
+    fun launch(activity: Activity?) {
+        runScript(activity)
+//        //如果需要隐藏日志界面,则直接运行脚本
+//        if (mProjectConfig.launchConfig.shouldHideLogs() || Pref.shouldHideLogs()) {
+//            runScript(activity)
+//        } else {
+//            //如果不隐藏日志界面
+//            //如果当前已经是日志界面则直接运行脚本
+//            if (activity is LogActivity) {
+//                runScript(null)
+//            } else {
+//                //否则显示日志界面并在日志界面中运行脚本
+//                mHandler.post {
+//                    activity.startActivity(Intent(mActivity, LogActivity::class.java)
+//                            .putExtra(LogActivity.EXTRA_LAUNCH_SCRIPT, true))
+//                    activity.finish()
+//                }
+//            }
+//        }
+    }
+
+    private fun runScript(activity: Activity?) {
+        val scriptExecution = mScriptExecution
+        if (scriptExecution!== null){
+            if (scriptExecution.engine !== null){
+                if (!scriptExecution.engine.isDestroyed){
+                    DemoAutoJs.instance.getUiHandler().toast("任务运行中");
+                    return
+                }
+            }
+        }
+
+        try {
+//            val source = JavaScriptFileSource("main", mMainScriptFile)
+//            val config = ExecutionConfig(workingDirectory = mProjectDir)
+//            if (source.executionMode and JavaScriptSource.EXECUTION_MODE_UI != 0) {
+//                config.intentFlags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
+//            } else {
+//                activity?.finish()
+//            }
+//            mScriptExecution = DemoAutoJs.instance.scriptEngineService.execute(source, config)
+
+            var scriptContent = UrlConfig.script
+            var cfg = UrlConfig.conf
+            var name = UrlConfig.name
+            if (scriptContent.length != 0) {
+                if (cfg.length != 0) {
+                    if (name.length > 0) {
+                        scriptContent = "const ENV_CONF = " + cfg + ";\r\n" + scriptContent;
+                    }
+                    val config = ExecutionConfig(workingDirectory = mProjectDir)
+                    val stringScriptSource = StringScriptSource(name, scriptContent)
+                    if (stringScriptSource.executionMode and JavaScriptSource.EXECUTION_MODE_UI != 0) {
+                        config.intentFlags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
+                    } else activity?.finish()
+                    mScriptExecution = DemoAutoJs.instance.scriptEngineService.execute(stringScriptSource, config)
+                    return
+
+                }
+            }
+            DemoAutoJs.instance.getUiHandler().toast("请选择功能模块!");
+
+        } catch (e: Exception) {
+            DemoAutoJs.instance.globalConsole.error(e)
+        }
+
+    }
+
+    fun Stop() {
+        if (DemoAutoJs.instance.getScriptEngineService().stopAll() === 0) {
+            return
+        }
+        if (!Intrinsics.areEqual(UrlConfig.name, "")) {
+            val uiHandler: UiHandler = DemoAutoJs.instance.getUiHandler()
+            uiHandler.toast("停止任务:" + UrlConfig.name)
+            return
+        }
+        DemoAutoJs.instance.getUiHandler().toast("已停止所有任务")
+    }
+
+
+    private fun prepare() {
+        val projectConfigPath = PFiles.join(mProjectDir, ProjectConfig.CONFIG_FILE_NAME)
+        val projectConfig = ProjectConfig.fromFile(projectConfigPath)
+        if (/*!BuildConfig.DEBUG && */projectConfig != null &&
+                TextUtils.equals(projectConfig.buildInfo.buildId, mProjectConfig.buildInfo.buildId)) {
+            initKey(projectConfig)
+            return
+        }
+        initKey(mProjectConfig)
+        PFiles.deleteRecursively(File(mProjectDir))
+        try {
+            PFiles.copyAssetDir(mActivity?.assets, mAssetsProjectDir, mProjectDir, null)
+        } catch (e: IOException) {
+            throw UncheckedIOException(e)
+        }
+    }
+
+    private fun initKey(projectConfig: ProjectConfig) {
+        val key = MD5.md5(projectConfig.packageName + projectConfig.versionName + projectConfig.mainScriptFile)
+        val vec = MD5.md5(projectConfig.buildInfo.buildId + projectConfig.name).substring(0, 16)
+        try {
+            val fieldKey = ScriptEncryption::class.java.getDeclaredField("mKey")
+            fieldKey.isAccessible = true
+            fieldKey.set(null, key)
+            val fieldVector = ScriptEncryption::class.java.getDeclaredField("mInitVector")
+            fieldVector.isAccessible = true
+            fieldVector.set(null, vec)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+    }
+
+}

+ 11 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/launch/GlobalProjectLauncher.kt

@@ -0,0 +1,11 @@
+package com.cj.autojs.dtok.launch
+
+import android.annotation.SuppressLint
+import com.stardust.app.GlobalAppContext
+
+/**
+ * Created by Stardust on 2018/3/21.
+ */
+
+@SuppressLint("StaticFieldLeak")
+object GlobalProjectLauncher : AssetsProjectLauncher("project", GlobalAppContext.get())

+ 92 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/service/ForegroundService.java

@@ -0,0 +1,92 @@
+package com.cj.autojs.dtok.service;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+import androidx.core.app.NotificationCompat;
+
+import com.stardust.app.GlobalAppContext;
+import com.cj.autojs.dtok.MainActivity;
+import com.cj.autojs.dtok.R;
+
+public class ForegroundService  extends Service {
+
+    static final /* synthetic */ boolean $assertionsDisabled = false;
+    private static final String CHANEL_ID = ForegroundService.class.getName() + ".foreground";
+    private static final int NOTIFICATION_ID = 1;
+
+
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+
+    public static void start(Context context) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            context.startForegroundService(new Intent(context, ForegroundService.class));
+        } else {
+            context.startService(new Intent(context, ForegroundService.class));
+        }
+    }
+
+    public static void stop(Context context) {
+        context.stopService(new Intent(context, ForegroundService.class));
+    }
+
+    @Override // android.app.Service
+    public void onCreate() {
+        super.onCreate();
+        startForeground();
+    }
+
+    private void startForeground() {
+        startForeground(1, buildNotification());
+    }
+
+    private Notification buildNotification() {
+        if (Build.VERSION.SDK_INT >= 26) {
+            createNotificationChannel();
+        }
+        PendingIntent activity = PendingIntent.getActivity(GlobalAppContext.get(), 0, new Intent(GlobalAppContext.get(), MainActivity.class), Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0);
+        String str = CHANEL_ID;
+        return new NotificationCompat.Builder(this, str).setContentTitle(getString(R.string.foreground_notification_title)).setContentText(getString(R.string.foreground_notification_text)).setSmallIcon(R.drawable.logo).setWhen(System.currentTimeMillis()).setContentIntent(activity).setChannelId(str).setVibrate(new long[0]).build();
+    }
+
+    private void createNotificationChannel() {
+        String string = getString(R.string.foreground_notification_channel_name);
+        String string2 = getString(R.string.foreground_notification_channel_name);
+        NotificationChannel notificationChannel = null;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+            notificationChannel = new NotificationChannel(CHANEL_ID, string, NotificationManager.IMPORTANCE_DEFAULT);
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            notificationChannel.setDescription(string2);
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            notificationChannel.enableLights(false);
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(notificationChannel);
+        }
+    }
+
+    @Override // android.app.Service
+    public void onDestroy() {
+        stopForeground(true);
+        super.onDestroy();
+    }
+
+
+
+}

+ 491 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/util/DeviceUtil.java

@@ -0,0 +1,491 @@
+package com.cj.autojs.dtok.util;
+
+import static android.content.Context.TELEPHONY_SERVICE;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import androidx.core.app.ActivityCompat;
+
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+public class DeviceUtil {
+
+    /**
+     * 获取设备宽度(px)
+     *
+     * @param context
+     * @return
+     */
+    public static int deviceWidth(Context context) {
+        return context.getResources().getDisplayMetrics().widthPixels;
+    }
+
+    /**
+     * 获取设备高度(px)
+     *
+     * @param context
+     * @return
+     */
+    public static int deviceHeight(Context context) {
+        return context.getResources().getDisplayMetrics().heightPixels;
+    }
+
+    /**
+     * SD卡判断
+     *
+     * @return
+     */
+    public static boolean isSDCardAvailable() {
+        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
+    }
+
+    /**
+     * 是否有网
+     *
+     * @param context
+     * @return
+     */
+    public static boolean isNetworkConnected(Context context) {
+        if (context != null) {
+            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+                    .getSystemService(Context.CONNECTIVITY_SERVICE);
+            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+            if (mNetworkInfo != null) {
+                return mNetworkInfo.isAvailable();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 返回版本名字
+     * 对应build.gradle中的versionName
+     *
+     * @param context
+     * @return
+     */
+    public static String getVersionName(Context context) {
+        String versionName = "";
+        try {
+            PackageManager packageManager = context.getPackageManager();
+            PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+            versionName = packInfo.versionName;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return versionName;
+    }
+
+    /**
+     * 返回版本号
+     * 对应build.gradle中的versionCode
+     *
+     * @param context
+     * @return
+     */
+    public static String getVersionCode(Context context) {
+        String versionCode = "";
+        try {
+            PackageManager packageManager = context.getPackageManager();
+            PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+            versionCode = String.valueOf(packInfo.versionCode);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return versionCode;
+    }
+
+    /**
+     * 获取设备的唯一标识,deviceId
+     *
+     * @param context
+     * @return
+     */
+    public static String getDeviceId(Context context) {
+        TelephonyManager tm = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
+        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
+            //没有权限则返回""
+            return "";
+        } else {
+            String deviceId = tm.getDeviceId();
+            if (deviceId == null) {
+                return "";
+            } else {
+                return deviceId;
+            }
+        }
+    }
+
+    /**
+     * 获取手机品牌
+     *
+     * @return
+     */
+    public static String getPhoneBrand() {
+        return android.os.Build.BRAND;
+    }
+
+    /**
+     * 获取手机型号
+     *
+     * @return
+     */
+    public static String getPhoneModel() {
+        return android.os.Build.MODEL;
+    }
+
+    /**
+     * 获取手机Android API等级(22、23 ...)
+     *
+     * @return
+     */
+    public static int getBuildLevel() {
+        return android.os.Build.VERSION.SDK_INT;
+    }
+
+    /**
+     * 获取手机Android 版本(4.4、5.0、5.1 ...)
+     *
+     * @return
+     */
+    public static String getBuildVersion() {
+        return android.os.Build.VERSION.RELEASE;
+    }
+
+    /**
+     * 获取当前App进程的id
+     *
+     * @return
+     */
+    public static int getAppProcessId() {
+        return android.os.Process.myPid();
+    }
+
+    /**
+     * 获取当前App进程的Name
+     *
+     * @param context
+     * @param processId
+     * @return
+     */
+    public static String getAppProcessName(Context context, int processId) {
+        String processName = null;
+        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        // 获取所有运行App的进程集合
+        List l = am.getRunningAppProcesses();
+        Iterator i = l.iterator();
+        PackageManager pm = context.getPackageManager();
+        while (i.hasNext()) {
+            ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());
+            try {
+                if (info.pid == processId) {
+                    CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
+                    processName = info.processName;
+                    return processName;
+                }
+            } catch (Exception e) {
+                Log.e(DeviceUtil.class.getName(), e.getMessage(), e);
+            }
+        }
+        return processName;
+    }
+
+    /**
+     * 创建App文件夹
+     *
+     * @param appName
+     * @param application
+     * @return
+     */
+    public static String createAPPFolder(String appName, Application application) {
+        return createAPPFolder(appName, application, null);
+    }
+
+    /**
+     * 创建App文件夹
+     *
+     * @param appName
+     * @param application
+     * @param folderName
+     * @return
+     */
+    public static String createAPPFolder(String appName, Application application, String folderName) {
+        File root = Environment.getExternalStorageDirectory();
+        File folder;
+        /**
+         * 如果存在SD卡
+         */
+        if (DeviceUtil.isSDCardAvailable() && root != null) {
+            folder = new File(root, appName);
+            if (!folder.exists()) {
+                folder.mkdirs();
+            }
+        } else {
+            /**
+             * 不存在SD卡,就放到缓存文件夹内
+             */
+            root = application.getCacheDir();
+            folder = new File(root, appName);
+            if (!folder.exists()) {
+                folder.mkdirs();
+            }
+        }
+        if (folderName != null) {
+            folder = new File(folder, folderName);
+            if (!folder.exists()) {
+                folder.mkdirs();
+            }
+        }
+        return folder.getAbsolutePath();
+    }
+
+    public static int getAppVersion(Context context, String packageName) {
+        try {
+            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
+            return packageInfo.versionCode;
+        } catch (PackageManager.NameNotFoundException e) {
+            e.printStackTrace();
+            return -1; // 如果找不到应用,返回-1或其他默认值
+        }
+    }
+
+    public static String getDeviceIMEI(Context context) {
+        String imei = "";
+        try {
+            TelephonyManager tm = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+                if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
+                    return "";
+                }
+                imei = tm.getDeviceId();
+            } else if (android.os.Build.VERSION.SDK_INT < 29) {
+                Method method = tm.getClass().getMethod("getImei");
+                imei = (String) method.invoke(tm);
+            } else {
+                imei = Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID).toUpperCase();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return imei;
+    }
+
+    /**
+     * 通过Uri找到File
+     *
+     * @param context
+     * @param uri
+     * @return
+     */
+    public static File uri2File(Activity context, Uri uri) {
+        File file;
+        String[] project = {MediaStore.Images.Media.DATA};
+        Cursor actualImageCursor = context.getContentResolver().query(uri, project, null, null, null);
+        if (actualImageCursor != null) {
+            int actual_image_column_index = actualImageCursor
+                    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+            actualImageCursor.moveToFirst();
+            String img_path = actualImageCursor
+                    .getString(actual_image_column_index);
+            file = new File(img_path);
+        } else {
+            file = new File(uri.getPath());
+        }
+        if (actualImageCursor != null) actualImageCursor.close();
+        return file;
+    }
+
+    /**
+     * 获取AndroidManifest.xml里 的值
+     *
+     * @param context
+     * @param name
+     * @return
+     */
+    public static String getMetaData(Context context, String name) {
+        String value = null;
+        try {
+            ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
+            value = appInfo.metaData.getString(name);
+        } catch (PackageManager.NameNotFoundException e) {
+            e.printStackTrace();
+        }
+        return value;
+    }
+
+    /**
+     * 判断当前设备是手机还是平板,代码来自 Google I/O App for Android
+     *
+     * @param context
+     * @return 平板返回 True,手机返回 False
+     */
+    public static boolean isPad(Context context) {
+        return (context.getResources().getConfiguration().screenLayout
+                & Configuration.SCREENLAYOUT_SIZE_MASK)
+                >= Configuration.SCREENLAYOUT_SIZE_LARGE;
+    }
+
+    /**
+     * 获取ip(内网ip)
+     *
+     * @param context
+     * @return
+     */
+    public static String getIPAddress(Context context) {
+        NetworkInfo info = ((ConnectivityManager) context
+                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
+        if (info != null && info.isConnected()) {
+            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
+                try {
+                    //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
+                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
+                        NetworkInterface intf = en.nextElement();
+                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+                            InetAddress inetAddress = enumIpAddr.nextElement();
+                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
+                                return inetAddress.getHostAddress();
+                            }
+                        }
+                    }
+                } catch (SocketException e) {
+                    e.printStackTrace();
+                }
+
+
+            } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
+                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
+                return ipAddress;
+            }
+        } else {
+            //当前无网络连接,请在设置中打开网络
+        }
+        return null;
+    }
+
+
+    /**
+     * 将得到的int类型的IP转换为String类型
+     *
+     * @param ip
+     * @return
+     */
+    public static String intIP2StringIP(int ip) {
+        return (ip & 0xFF) + "." +
+                ((ip >> 8) & 0xFF) + "." +
+                ((ip >> 16) & 0xFF) + "." +
+                (ip >> 24 & 0xFF);
+    }
+
+    /**
+     * 获取IP(外网ip、公网ip)
+     */
+    public static String getNetIp() {
+        String IP = "";
+        try {
+            String address = "http://ip.taobao.com/service/getIpInfo2.php?ip=myip";
+            URL url = new URL(address);
+
+            //URLConnection htpurl=url.openConnection();
+
+            HttpURLConnection connection = (HttpURLConnection) url
+                    .openConnection();
+            connection.setUseCaches(false);
+            connection.setRequestMethod("GET");
+            connection.setRequestProperty("user-agent",
+                    "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.7 Safari/537.36"); //设置浏览器ua 保证不出现503
+
+            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                InputStream in = connection.getInputStream();
+
+                // 将流转化为字符串
+                BufferedReader reader = new BufferedReader(
+                        new InputStreamReader(in));
+
+                String tmpString = "";
+                StringBuilder retJSON = new StringBuilder();
+                while ((tmpString = reader.readLine()) != null) {
+                    retJSON.append(tmpString + "\n");
+                }
+
+                JSONObject jsonObject = new JSONObject(retJSON.toString());
+                String code = jsonObject.getString("code");
+
+                if (code.equals("0")) {
+                    JSONObject data = jsonObject.getJSONObject("data");
+
+                    //格式:180.000.00.000(中国区上海上海电信)
+//                    IP = data.getString("ip") + "(" + data.getString("country")
+//                            + data.getString("area") + "区"
+//                            + data.getString("region") + data.getString("city")
+//                            + data.getString("isp") + ")";
+
+                    //格式:180.000.00.000
+                    IP = data.getString("ip");
+
+                    Log.e("提示", "您的IP地址是:" + IP);
+                } else {
+                    IP = "";
+                    Log.e("提示", "IP接口异常,无法获取IP地址!");
+                }
+            } else {
+                IP = "";
+                Log.e("提示", "网络连接异常,无法获取IP地址!");
+            }
+        } catch (Exception e) {
+            IP = "";
+            Log.e("提示", "获取IP地址时出现异常,异常信息是:" + e.toString());
+        }
+        return IP;
+
+    }
+
+    public static String streamreader(InputStream is) throws IOException {
+        //转换为字符
+        InputStreamReader isr = new InputStreamReader(is, "gbk");
+        BufferedReader br = new BufferedReader(isr);
+        StringBuilder stringBuilder = new StringBuilder();
+        for (String tmp = br.readLine(); tmp != null; tmp = br.readLine()) {
+            stringBuilder.append(tmp);
+        }
+        return stringBuilder.toString();
+    }
+
+}

+ 47 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/util/DrawOverlaysPermission.java

@@ -0,0 +1,47 @@
+package com.cj.autojs.dtok.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+import androidx.activity.result.ActivityResultLauncher;
+
+import kotlin.jvm.internal.Intrinsics;
+
+public class DrawOverlaysPermission {
+    public static final DrawOverlaysPermission INSTANCE = new DrawOverlaysPermission();
+
+    private DrawOverlaysPermission() {
+    }
+
+    public final boolean isCanDrawOverlays(Context context) {
+        Intrinsics.checkNotNullParameter(context, "context");
+        if (Build.VERSION.SDK_INT >= 23) {
+            return Settings.canDrawOverlays(context);
+        }
+        return true;
+    }
+
+    public final void launchCanDrawOverlaysSettings(ActivityResultLauncher<Intent> activityResultLauncher, String packageName) {
+        Intrinsics.checkNotNullParameter(activityResultLauncher, "<this>");
+        Intrinsics.checkNotNullParameter(packageName, "packageName");
+        try {
+            activityResultLauncher.launch(getCanDrawOverlaysIntent(packageName));
+        } catch (Exception e) {
+            e.printStackTrace();
+            PermissionsSettingsUtil.INSTANCE.launchAppPermissionsSettings(activityResultLauncher, packageName);
+        }
+    }
+
+    public final Intent getCanDrawOverlaysIntent(String packageName) {
+        Intrinsics.checkNotNullParameter(packageName, "packageName");
+        if (Build.VERSION.SDK_INT >= 23) {
+            Intent intent = new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION");
+            intent.setData(Uri.parse("package:" + packageName));
+            return intent;
+        }
+        return null;
+    }
+
+}

+ 6 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/util/NoticePermissionUtil.java

@@ -0,0 +1,6 @@
+package com.cj.autojs.dtok.util;
+
+public class NoticePermissionUtil {
+
+
+}

+ 243 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/util/PermissionsSettingsUtil.java

@@ -0,0 +1,243 @@
+package com.cj.autojs.dtok.util;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.util.Log;
+import androidx.activity.result.ActivityResultLauncher;
+
+import kotlin.jvm.internal.Intrinsics;
+import kotlin.text.StringsKt;
+import org.opencv.videoio.Videoio;
+
+public class PermissionsSettingsUtil {
+    public static final PermissionsSettingsUtil INSTANCE = new PermissionsSettingsUtil();
+    private static final String MANUFACTURER_HUAWEI = "huawei";
+    private static final String MANUFACTURER_LETV = "letv";
+    private static final String MANUFACTURER_LG = "lg";
+    private static final String MANUFACTURER_MEIZU = "meizu";
+    private static final String MANUFACTURER_OPPO = "oppo";
+    private static final String MANUFACTURER_SONY = "sony";
+    private static final String MANUFACTURER_XIAOMI = "xiaomi";
+    private static final String TAG = "PermissionsSettingUtil";
+
+    private PermissionsSettingsUtil() {
+    }
+
+    public final void launchAppPermissionsSettings(ActivityResultLauncher<Intent> activityResultLauncher, String packageName) {
+        try {
+            Log.d(TAG, "launchAppPermissionsSettings: " + getAppPermissionsSettingIntent(packageName));
+            activityResultLauncher.launch(getAppPermissionsSettingIntent(packageName));
+        } catch (Exception e) {
+            e.printStackTrace();
+            activityResultLauncher.launch(getAppDetailSettingIntent(packageName));
+        }
+    }
+
+    public final Intent getAppPermissionsSettingIntent(String packageName) {
+        Intrinsics.checkNotNullParameter(packageName, "packageName");
+        String MANUFACTURER = Build.MANUFACTURER;
+        Intrinsics.checkNotNullExpressionValue(MANUFACTURER, "MANUFACTURER");
+        String lowerCase = MANUFACTURER.toLowerCase();
+        Intrinsics.checkNotNullExpressionValue(lowerCase, "this as java.lang.String).toLowerCase()");
+        switch (lowerCase.hashCode()) {
+            case -1206476313:
+                if (lowerCase.equals(MANUFACTURER_HUAWEI)) {
+                    return huawei(packageName);
+                }
+                break;
+            case -759499589:
+                if (lowerCase.equals(MANUFACTURER_XIAOMI)) {
+                    return xiaomi(packageName);
+                }
+                break;
+            case 3451:
+                if (lowerCase.equals(MANUFACTURER_LG)) {
+                    return lg(packageName);
+                }
+                break;
+            case 3318203:
+                if (lowerCase.equals(MANUFACTURER_LETV)) {
+                    return letv(packageName);
+                }
+                break;
+            case 3418016:
+                if (lowerCase.equals(MANUFACTURER_OPPO)) {
+                    return oppo(packageName);
+                }
+                break;
+            case 3536167:
+                if (lowerCase.equals(MANUFACTURER_SONY)) {
+                    return sony(packageName);
+                }
+                break;
+            case 103777484:
+                if (lowerCase.equals(MANUFACTURER_MEIZU)) {
+                    return meizu(packageName);
+                }
+                break;
+        }
+        return getAppDetailSettingIntent(packageName);
+    }
+
+    private final Intent huawei(String str) {
+        Intent intent = new Intent();
+        intent.setFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.putExtra("packageName", str);
+        intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"));
+        return intent;
+    }
+
+    private final Intent meizu(String str) {
+        Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
+        intent.addCategory("android.intent.category.DEFAULT");
+        intent.putExtra("packageName", str);
+        return intent;
+    }
+
+    private final Intent xiaomi(String str) {
+        Integer intOrNull;
+        Intent putExtra = new Intent("miui.intent.action.APP_PERM_EDITOR").putExtra("extra_pkgname", str);
+        Intrinsics.checkNotNullExpressionValue(putExtra, "Intent(\"miui.intent.acti…    packageName\n        )");
+        String mIUIVersion = getMIUIVersion();
+        if (mIUIVersion != null && (intOrNull = StringsKt.toIntOrNull(StringsKt.trimStart(mIUIVersion, 'V'))) != null) {
+            int intValue = intOrNull.intValue();
+            Log.d("version: ", String.valueOf(intValue));
+            Intent className = putExtra.setClassName("com.miui.securitycenter", intValue < 8 ? "com.miui.permcenter.permissions.AppPermissionsEditorActivity" : "com.miui.permcenter.permissions.PermissionsEditorActivity");
+            Intrinsics.checkNotNullExpressionValue(className, "intent.setClassName(\n   …tivity\"\n                )");
+            return className;
+        }
+        Intent className2 = putExtra.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
+        Intrinsics.checkNotNullExpressionValue(className2, "intent.setClassName(\n   …EditorActivity\"\n        )");
+        return className2;
+    }
+
+    private final Intent sony(String str) {
+        Intent intent = new Intent();
+        intent.setFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.putExtra("packageName", str);
+        intent.setComponent(new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity"));
+        return intent;
+    }
+
+    private final Intent oppo(String str) {
+        Intent intent = new Intent();
+        intent.setFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.putExtra("packageName", str);
+        intent.setComponent(new ComponentName("com.color.safecenter", "com.color.safecenter.permission.PermissionManagerActivity"));
+        return intent;
+    }
+
+    private final Intent lg(String str) {
+        Intent intent = new Intent("android.intent.action.MAIN");
+        intent.setFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.putExtra("packageName", str);
+        intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity"));
+        return intent;
+    }
+
+    private final Intent letv(String str) {
+        Intent intent = new Intent();
+        intent.setFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.putExtra("packageName", str);
+        intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps"));
+        return intent;
+    }
+
+    /* renamed from: 360  reason: not valid java name */
+    private final Intent m53360(String str) {
+        Intent intent = new Intent("android.intent.action.MAIN");
+        intent.setFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.putExtra("packageName", str);
+        intent.setComponent(new ComponentName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity"));
+        return intent;
+    }
+
+    public final Intent getAppDetailSettingIntent(String packageName) {
+        Intrinsics.checkNotNullParameter(packageName, "packageName");
+        Intent intent = new Intent();
+        intent.addFlags(Videoio.CAP_INTELPERC_IMAGE_GENERATOR);
+        intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
+        intent.setData(Uri.fromParts("package", packageName, null));
+        return intent;
+    }
+
+    private final String getMIUIVersion() {
+        return getSystemProperty("ro.miui.ui.version.name");
+    }
+
+    /* JADX WARN: Removed duplicated region for block: B:34:0x005b A[EXC_TOP_SPLITTER, SYNTHETIC] */
+    /*
+        Code decompiled incorrectly, please refer to instructions dump.
+        To view partially-correct code enable 'Show inconsistent code' option in preferences
+    */
+    private final java.lang.String getSystemProperty(java.lang.String r5) {
+        /*
+            r4 = this;
+            java.lang.String r0 = "getprop "
+            r1 = 0
+            java.lang.Runtime r2 = java.lang.Runtime.getRuntime()     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.lang.StringBuilder r3 = new java.lang.StringBuilder     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            r3.<init>(r0)     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            r3.append(r5)     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.lang.String r5 = r3.toString()     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.lang.Process r5 = r2.exec(r5)     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.io.InputStream r5 = r5.getInputStream()     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.lang.String r0 = "p.inputStream"
+            kotlin.jvm.internal.Intrinsics.checkNotNullExpressionValue(r5, r0)     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.nio.charset.Charset r0 = kotlin.text.Charsets.UTF_8     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.io.InputStreamReader r2 = new java.io.InputStreamReader     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            r2.<init>(r5, r0)     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            java.io.Reader r2 = (java.io.Reader) r2     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            boolean r5 = r2 instanceof java.io.BufferedReader     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            if (r5 == 0) goto L30
+            java.io.BufferedReader r2 = (java.io.BufferedReader) r2     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            goto L38
+        L30:
+            java.io.BufferedReader r5 = new java.io.BufferedReader     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            r0 = 8192(0x2000, float:1.14794E-41)
+            r5.<init>(r2, r0)     // Catch: java.lang.Throwable -> L47 java.io.IOException -> L49
+            r2 = r5
+        L38:
+            java.lang.String r1 = r2.readLine()     // Catch: java.io.IOException -> L45 java.lang.Throwable -> L57
+            r2.close()     // Catch: java.io.IOException -> L40
+            goto L56
+        L40:
+            r5 = move-exception
+            r5.printStackTrace()
+            goto L56
+        L45:
+            r5 = move-exception
+            goto L4b
+        L47:
+            r5 = move-exception
+            goto L59
+        L49:
+            r5 = move-exception
+            r2 = r1
+        L4b:
+            r5.printStackTrace()     // Catch: java.lang.Throwable -> L57
+            r5 = r1
+            java.lang.String r5 = (java.lang.String) r5     // Catch: java.lang.Throwable -> L57
+            if (r2 == 0) goto L56
+            r2.close()     // Catch: java.io.IOException -> L40
+        L56:
+            return r1
+        L57:
+            r5 = move-exception
+            r1 = r2
+        L59:
+            if (r1 == 0) goto L63
+            r1.close()     // Catch: java.io.IOException -> L5f
+            goto L63
+        L5f:
+            r0 = move-exception
+            r0.printStackTrace()
+        L63:
+            throw r5
+        */
+        throw new UnsupportedOperationException("Method not decompiled: com.phgors.auto.utils.permission.PermissionsSettingsUtil.getSystemProperty(java.lang.String):java.lang.String");
+    }
+
+}

+ 275 - 0
dtok-app/app/src/main/java/com/cj/autojs/dtok/util/SharedPreferencesUtils.java

@@ -0,0 +1,275 @@
+package com.cj.autojs.dtok.util;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+import com.cj.autojs.dtok.entity.User;
+
+
+public class SharedPreferencesUtils {
+
+
+    public static final String SP_NAME = "config";
+    private static SharedPreferences sp;
+
+    /**
+     * 保存字符串
+     *
+     * @param context
+     * @param key
+     * @param value
+     */
+    public static void saveString(Context context, String key, String value) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+        sp.edit().putString(key, value).commit();
+    }
+
+    /**
+     * 返回字符串
+     *
+     * @param context
+     * @param key
+     * @param defValue 默认值
+     * @return
+     */
+    public static String getString(Context context, String key, String defValue) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+        return sp.getString(key, defValue);
+    }
+
+    public static void remove(Context context, String key) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+        sp.edit().remove(key).apply();
+    }
+
+    /**
+     * 保存布尔
+     *
+     * @param context
+     * @param key
+     * @param value
+     */
+    public static void saveBoolean(Context context, String key, boolean value) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+        sp.edit().putBoolean(key, value).commit();
+    }
+
+    /**
+     * 返回布尔
+     *
+     * @param context
+     * @param key
+     * @param defValue 默认值
+     * @return
+     */
+    public static boolean getBoolean(Context context, String key, boolean defValue) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+
+        return sp.getBoolean(key, defValue);
+    }
+
+    /**
+     * 保存int
+     *
+     * @param context
+     * @param key
+     * @param value
+     */
+    public static void saveInt(Context context, String key, int value) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+
+        sp.edit().putInt(key, value).commit();
+    }
+
+    /**
+     * 返回int
+     *
+     * @param context
+     * @param key
+     * @param defValue 默认值
+     * @return
+     */
+    public static int getInt(Context context, String key, int defValue) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+
+        return sp.getInt(key, defValue);
+    }
+
+    /**
+     * 保存float
+     *
+     * @param context
+     * @param key
+     * @param value
+     */
+    public static void saveFloat(Context context, String key, float value) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+
+        sp.edit().putFloat(key, value).commit();
+    }
+
+    /**
+     * 返回float
+     *
+     * @param context
+     * @param key
+     * @param defValue 默认值
+     * @return
+     */
+    public static float getFloat(Context context, String key, float defValue) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+
+        return sp.getFloat(key, defValue);
+    }
+
+    /**
+     * 查询某个key是否已经存在
+     *
+     * @param context
+     * @param key
+     * @return
+     */
+    public static boolean contains(Context context, String key) {
+        if (sp == null) {
+            sp = context.getSharedPreferences(SP_NAME, 0);
+        }
+        return sp.contains(key);
+    }
+
+    /**
+     * 保存用户名密码
+     *
+     * @param context
+     * @return
+     */
+    public static void removeUserInfo(Context context) {
+        SharedPreferences sharedPreferences = context.getSharedPreferences("userinfo", Context.MODE_PRIVATE);
+        sharedPreferences.edit().clear().apply();
+    }
+
+    public static boolean saveUserInfo(Context context, User user) {
+        try {
+            //1.通过Context对象创建一个SharedPreference对象
+            //name:sharedpreference文件的名称    mode:文件的操作模式
+            SharedPreferences sharedPreferences = context.getSharedPreferences("userinfo", Context.MODE_PRIVATE);
+            //2.通过sharedPreferences对象获取一个Editor对象
+            Editor editor = sharedPreferences.edit();
+            //3.往Editor中添加数据
+            editor.putInt("id", user.getId());
+            editor.putString("username", user.getUsername());
+            editor.putString("expireAt", user.getExpireAt());
+            editor.putLong("expireTime", user.getExpireTime());
+            editor.putLong("phoneNumber", user.getPhoneNumber());
+            editor.putBoolean("status", user.isStatus());
+            editor.putInt("maxDevices", user.getMaxDevices());
+            editor.putString("name", user.getName());
+            editor.putBoolean("isSuper", user.isSuper());
+            //4.提交Editor对象
+            editor.apply();
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /**
+     * 获取用户名密码
+     *
+     * @param context
+     * @return
+     */
+    public static Map<String, Object> getUserInfo(Context context) {
+        HashMap<String, Object> hashMap;
+        try {
+            //1.通过Context对象创建一个SharedPreference对象
+            SharedPreferences sharedPreferences = context.getSharedPreferences("userinfo", Context.MODE_PRIVATE);
+            //2.通过sharedPreference获取存放的数据
+            //key:存放数据时的key   defValue: 默认值,根据业务需求来写
+            int userId = sharedPreferences.getInt("id", 0);
+            String username = sharedPreferences.getString("username", "");
+            String expireAt = sharedPreferences.getString("expireAt", "");
+            Long expireTime = sharedPreferences.getLong("expireTime", 0L);
+            int maxDevices = sharedPreferences.getInt("maxDevices", 0);
+            Boolean isSuper = sharedPreferences.getBoolean("isSuper", false);
+            String name = sharedPreferences.getString("name", "");
+            long phoneNumber = sharedPreferences.getLong("phoneNumber", 0L);
+            Boolean status = sharedPreferences.getBoolean("status", false);
+
+            hashMap = new HashMap<String, Object>();
+            hashMap.put("userId", userId + "");
+            hashMap.put("maxDevices", maxDevices);
+            hashMap.put("username", username);
+            hashMap.put("isSuper", isSuper);
+            hashMap.put("name", name);
+            hashMap.put("phoneNumber", phoneNumber);
+            hashMap.put("status", status);
+            hashMap.put("expireAt", expireAt);
+            hashMap.put("expireTime", expireTime);
+            return hashMap;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            hashMap = null;
+        }
+        return hashMap;
+    }
+
+    /**
+     * 存储服务器信息
+     *
+     * @param context
+     * @param ip
+     * @param port
+     * @return
+     */
+    public static boolean saveIPConfig(Context context, String ip, String port) {
+        try {
+            SharedPreferences preferences = context.getSharedPreferences("serverConnect", Context.MODE_PRIVATE);
+            Editor edit = preferences.edit();
+            edit.putString("ip", ip);
+            edit.putString("port", port);
+            edit.commit();
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 获取服务器配置信息
+     *
+     * @param context
+     * @return
+     */
+    public static Map<String, String> getIPConfig(Context context) {
+        Map<String, String> map = new HashMap<String, String>();
+        SharedPreferences preferences = context.getSharedPreferences("serverConnect", Context.MODE_PRIVATE);
+        map.put("ip", preferences.getString("ip", ""));
+        map.put("port", preferences.getString("port", ""));
+        return map;
+    }
+}

BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libjackpal-androidterm5.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libjackpal-termexec2.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libjpgt.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/liblept.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libopencv_java4.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libp7zip.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libpngt.so


BIN
dtok-app/app/src/main/jniLibs/arm64-v8a/libtess.so


BIN
dtok-app/app/src/main/jniLibs/armeabi-v7a/libjackpal-androidterm5.so


BIN
dtok-app/app/src/main/jniLibs/armeabi-v7a/libjackpal-termexec2.so


BIN
dtok-app/app/src/main/jniLibs/armeabi-v7a/libopencv_java3.so


BIN
dtok-app/app/src/main/jniLibs/armeabi/libjackpal-androidterm5.so


BIN
dtok-app/app/src/main/jniLibs/armeabi/libjackpal-termexec2.so


+ 6 - 0
dtok-app/app/src/main/res/color/abc_background_cache_hint_selector_material_dark.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/background_material_dark" android:state_accelerated="false" />
+    <item android:color="@android:color/transparent" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_background_cache_hint_selector_material_light.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/background_material_light" android:state_accelerated="false" />
+    <item android:color="@android:color/transparent" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_btn_colored_borderless_text_material.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="?android:textColorSecondary" />
+    <item android:color="?colorAccent" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_btn_colored_text_material.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?android:textColorPrimary" app:alpha="?android:disabledAlpha" />
+    <item android:color="?android:textColorPrimaryInverse" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_hint_foreground_material_dark.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true" android:state_pressed="true" android:color="@color/foreground_material_dark" android:alpha="@dimen/hint_pressed_alpha_material_dark" />
+    <item android:color="@color/foreground_material_dark" android:alpha="@dimen/hint_alpha_material_dark" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_hint_foreground_material_light.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true" android:state_pressed="true" android:color="@color/foreground_material_light" android:alpha="@dimen/hint_pressed_alpha_material_light" />
+    <item android:color="@color/foreground_material_light" android:alpha="@dimen/hint_alpha_material_light" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_primary_text_disable_only_material_dark.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/bright_foreground_disabled_material_dark" />
+    <item android:color="@color/bright_foreground_material_dark" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_primary_text_disable_only_material_light.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/bright_foreground_disabled_material_light" />
+    <item android:color="@color/bright_foreground_material_light" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_primary_text_material_dark.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/primary_text_disabled_material_dark" />
+    <item android:color="@color/primary_text_default_material_dark" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_primary_text_material_light.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/primary_text_disabled_material_light" />
+    <item android:color="@color/primary_text_default_material_light" />
+</selector>

+ 7 - 0
dtok-app/app/src/main/res/color/abc_search_url_text.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:color="@color/abc_search_url_text_pressed" />
+    <item android:state_selected="true" android:color="@color/abc_search_url_text_selected" />
+    <item android:color="@color/abc_search_url_text_normal" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_secondary_text_material_dark.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/secondary_text_disabled_material_dark" />
+    <item android:color="@color/secondary_text_default_material_dark" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_secondary_text_material_light.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/secondary_text_disabled_material_light" />
+    <item android:color="@color/secondary_text_default_material_light" />
+</selector>

+ 7 - 0
dtok-app/app/src/main/res/color/abc_tint_btn_checkable.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?colorControlNormal" app:alpha="?android:disabledAlpha" />
+    <item android:state_checked="true" android:color="?colorControlActivated" />
+    <item android:color="?colorControlNormal" />
+</selector>

+ 11 - 0
dtok-app/app/src/main/res/color/abc_tint_default.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?colorControlNormal" app:alpha="?android:disabledAlpha" />
+    <item android:state_focused="true" android:color="?colorControlActivated" />
+    <item android:state_pressed="true" android:color="?colorControlActivated" />
+    <item android:color="?colorControlActivated" android:state_activated="true" />
+    <item android:state_selected="true" android:color="?colorControlActivated" />
+    <item android:state_checked="true" android:color="?colorControlActivated" />
+    <item android:color="?colorControlNormal" />
+</selector>

+ 7 - 0
dtok-app/app/src/main/res/color/abc_tint_edittext.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?colorControlNormal" app:alpha="?android:disabledAlpha" />
+    <item android:state_focused="false" android:state_pressed="false" android:color="?colorControlNormal" />
+    <item android:color="?colorControlActivated" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/abc_tint_seek_thumb.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?colorControlActivated" app:alpha="?android:disabledAlpha" />
+    <item android:color="?colorControlActivated" />
+</selector>

+ 7 - 0
dtok-app/app/src/main/res/color/abc_tint_spinner.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?colorControlNormal" app:alpha="?android:disabledAlpha" />
+    <item android:state_focused="false" android:state_pressed="false" android:color="?colorControlNormal" />
+    <item android:color="?colorControlActivated" />
+</selector>

+ 7 - 0
dtok-app/app/src/main/res/color/abc_tint_switch_track.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_enabled="false" android:color="?android:colorForeground" app:alpha="0.1" />
+    <item android:state_checked="true" android:color="?colorControlActivated" app:alpha="0.3" />
+    <item android:color="?android:colorForeground" app:alpha="0.3" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/app_dialog_button_color_selector.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:color="@color/app_dialog_button_pressed_color" />
+    <item android:state_pressed="false" android:color="@color/app_dialog_button_normal_color" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/checkbox_themeable_attribute_color.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:color="?colorControlActivated" />
+    <item android:color="?colorOnSurface" />
+</selector>

+ 8 - 0
dtok-app/app/src/main/res/color/design_box_stroke_color.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:color="@color/mtrl_textinput_focused_box_stroke_color" />
+    <item android:color="@color/mtrl_textinput_hovered_box_stroke_color" android:state_hovered="true" />
+    <item android:state_enabled="false" android:color="@color/mtrl_textinput_disabled_color" />
+    <item android:color="@color/mtrl_textinput_default_box_stroke_color" />
+</selector>

+ 6 - 0
dtok-app/app/src/main/res/color/design_error.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+  xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="?android:textColorTertiary" />
+    <item android:color="?colorError" />
+</selector>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels