├── .github ├── FUNDING.yml └── workflows │ └── android.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_EN.md ├── README_JP.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── contributors.json │ └── data │ │ ├── entry.json │ │ ├── gesture.json │ │ ├── material.json │ │ ├── recruit.json │ │ ├── resolution.json │ │ └── slogan.json │ ├── ic_launcher-playstore.png │ ├── kotlin │ └── com │ │ └── icebem │ │ └── akt │ │ ├── ArkApp.kt │ │ ├── adapter │ │ └── MaterialAdapter.kt │ │ ├── model │ │ ├── ContributorInfo.kt │ │ ├── HeadhuntCounter.kt │ │ ├── MaterialInfo.kt │ │ ├── OperatorInfo.kt │ │ ├── RecruitTag.kt │ │ └── RecruitViewer.kt │ │ ├── overlay │ │ ├── OverlayToast.kt │ │ └── OverlayView.kt │ │ ├── service │ │ ├── GestureService.kt │ │ ├── OverlayService.kt │ │ └── QSTileService.kt │ │ ├── ui │ │ ├── about │ │ │ └── AboutFragment.kt │ │ ├── home │ │ │ └── HomeFragment.kt │ │ ├── main │ │ │ └── MainActivity.kt │ │ ├── recruit │ │ │ └── RecruitFragment.kt │ │ └── settings │ │ │ └── SettingsFragment.kt │ │ └── util │ │ ├── ArkContributors.kt │ │ ├── ArkData.kt │ │ ├── ArkIO.kt │ │ ├── ArkMaid.kt │ │ ├── ArkPref.kt │ │ ├── Random.kt │ │ └── Resolution.kt │ └── res │ ├── animator │ ├── anim_core_alpha.xml │ ├── anim_core_scale_x.xml │ ├── anim_core_scale_y.xml │ ├── anim_default.xml │ └── anim_error_scale.xml │ ├── color │ └── color_checkbox_text.xml │ ├── drawable │ ├── bg_checkbox.xml │ ├── bg_checkbox_star_1.xml │ ├── bg_checkbox_star_2.xml │ ├── bg_checkbox_star_3.xml │ ├── bg_checkbox_star_4.xml │ ├── bg_checkbox_star_5.xml │ ├── bg_checkbox_star_6.xml │ ├── bg_floating.xml │ ├── bg_oval.xml │ ├── bg_overlay.xml │ ├── bg_tag.xml │ ├── bg_tag_star_1.xml │ ├── bg_tag_star_2.xml │ ├── bg_tag_star_3.xml │ ├── bg_tag_star_4.xml │ ├── bg_tag_star_5.xml │ ├── bg_tag_star_6.xml │ ├── bg_tag_unchecked.xml │ ├── bg_toast.xml │ ├── ic_add.xml │ ├── ic_akt.xml │ ├── ic_collapse.xml │ ├── ic_counter.xml │ ├── ic_error.xml │ ├── ic_exit.xml │ ├── ic_headhunt_toggle.xml │ ├── ic_info.xml │ ├── ic_language.xml │ ├── ic_launch.xml │ ├── ic_launcher_background.xml │ ├── ic_launcher_foreground.xml │ ├── ic_launcher_monochrome.xml │ ├── ic_layers.xml │ ├── ic_lightbulb.xml │ ├── ic_menu.xml │ ├── ic_night.xml │ ├── ic_place.xml │ ├── ic_recruit.xml │ ├── ic_remove.xml │ ├── ic_settings.xml │ ├── ic_sort.xml │ ├── ic_state_error.xml │ ├── ic_state_error_anim.xml │ ├── ic_state_ready.xml │ ├── ic_state_ready_anim.xml │ ├── ic_state_running.xml │ ├── ic_state_running_anim.xml │ ├── ic_storage.xml │ ├── ic_timer.xml │ ├── ic_update.xml │ └── ripple_tag.xml │ ├── layout │ ├── activity_main.xml │ ├── content_main.xml │ ├── dialog_input.xml │ ├── fragment_about.xml │ ├── fragment_home.xml │ ├── fragment_recruit.xml │ ├── overlay_counter.xml │ ├── overlay_material.xml │ ├── overlay_menu.xml │ ├── overlay_recruit.xml │ ├── qr_alipay.xml │ ├── qr_wechat.xml │ └── tag_overlay.xml │ ├── menu │ ├── menu_home.xml │ └── menu_tools.xml │ ├── mipmap-anydpi-v26 │ └── ic_launcher.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── qr_alipay.webp │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── qr_wechat.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── mipmap │ ├── mtl_30011.png │ ├── mtl_30012.png │ ├── mtl_30013.png │ ├── mtl_30014.png │ ├── mtl_30021.png │ ├── mtl_30022.png │ ├── mtl_30023.png │ ├── mtl_30024.png │ ├── mtl_30031.png │ ├── mtl_30032.png │ ├── mtl_30033.png │ ├── mtl_30034.png │ ├── mtl_30041.png │ ├── mtl_30042.png │ ├── mtl_30043.png │ ├── mtl_30044.png │ ├── mtl_30051.png │ ├── mtl_30052.png │ ├── mtl_30053.png │ ├── mtl_30054.png │ ├── mtl_30061.png │ ├── mtl_30062.png │ ├── mtl_30063.png │ ├── mtl_30064.png │ ├── mtl_30073.png │ ├── mtl_30074.png │ ├── mtl_30083.png │ ├── mtl_30084.png │ ├── mtl_30093.png │ ├── mtl_30094.png │ ├── mtl_30103.png │ ├── mtl_30104.png │ ├── mtl_31013.png │ ├── mtl_31014.png │ ├── mtl_31023.png │ ├── mtl_31024.png │ ├── mtl_31033.png │ ├── mtl_31034.png │ ├── mtl_31043.png │ ├── mtl_31044.png │ ├── mtl_31053.png │ ├── mtl_31054.png │ ├── mtl_31063.png │ └── mtl_31064.png │ ├── navigation │ └── mobile_navigation.xml │ ├── values-en │ └── strings.xml │ ├── values-fr │ └── strings.xml │ ├── values-in │ └── strings.xml │ ├── values-ja │ └── strings.xml │ ├── values-night │ ├── colors.xml │ └── themes.xml │ ├── values │ ├── arrays.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ ├── styles.xml │ └── themes.xml │ └── xml │ ├── accessibility_config.xml │ ├── filepaths.xml │ └── root_preferences.xml ├── build.gradle.kts ├── fastlane └── metadata │ └── android │ ├── en-US │ ├── full_description.txt │ ├── images │ │ └── icon.png │ ├── short_description.txt │ └── title.txt │ └── zh-CN │ ├── full_description.txt │ ├── images │ └── icon.png │ ├── short_description.txt │ └── title.txt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── signing.properties.sample /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: aistra0528 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: "https://www.paypal.me/aistra0528" 14 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths-ignore: 8 | - '**.md' 9 | - 'fastlane/**' 10 | - '.github/**' 11 | - '!.github/workflows/android.yml' 12 | pull_request: 13 | branches: 14 | - master 15 | paths-ignore: 16 | - '**.md' 17 | - 'fastlane/**' 18 | - '.github/**' 19 | - '!.github/workflows/android.yml' 20 | 21 | jobs: 22 | build: 23 | runs-on: ubuntu-latest 24 | if: ${{ !startsWith(github.event.head_commit.message, '[skip ci]') && github.repository_owner == 'aistra0528' }} 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | - name: Setup Java JDK 29 | uses: actions/setup-java@v3 30 | with: 31 | java-version: 17 32 | distribution: 'temurin' 33 | - name: Grant execute permission for gradlew 34 | run: chmod +x gradlew 35 | - name: Build with Gradle 36 | run: ./gradlew assembleDebug 37 | - name: Upload a Build Artifact 38 | uses: actions/upload-artifact@v3 39 | with: 40 | name: Debug 41 | path: app/build/outputs/apk/debug 42 | retention-days: 7 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | /.idea/ 3 | /build/ 4 | /local.properties 5 | /signing.properties 6 | *.iml 7 | *.jks 8 | *.keystore -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This project is no longer maintained 2 | # 此项目不再维护 3 | 4 | 简体中文 | [English](README_EN.md) | [日本語](README_JP.md) 5 | # 方舟帮帮忙 6 | 方舟帮帮忙是一款辅助博士们游玩明日方舟的自由软件。 7 | 8 | [在酷安上获取](https://www.coolapk.com/apk/com.icebem.akt) 9 | ## 功能 10 | ### 帮帮忙™ 11 | 一个提供各种实用功能的悬浮球,可从通知栏“快速设置”图块打开。 12 | #### 公开招募规划 13 | 使用5个需求标签组合出可能的方案。 14 | - 多渠道不同干员进度,明日方舟(含哔哩哔哩和龍成網路客户端)、Arknights 、アークナイツ 和 명일방주 随心切换,无需更改系统语言 15 | - 支持招募时限选择 16 | - 触摸标题时隐藏内容,抬起重置标签 17 | #### 寻访计数器 18 | 记录已寻访次数并获取下次获得6★概率。 19 | #### 材料来源推荐 20 | 提供养成材料的高性价比掉落关卡。 21 | ### 戳戳乐™ 22 | **在关于界面一直戳“版本类型”,更新为 Originium 后覆盖安装应用或重启设备即可解除封印** 23 | 24 | 可选择非剿灭作战关卡持续进行代理作战,解放双手,不用一直盯着屏幕。 25 | - Android 7.0 及更高版本基于无障碍 API 实现,无需 ADB 或 Root 权限 26 | - 不截取屏幕内容,支持多分辨率 27 | - 可设置行动间隔和时长,自带波动间隔(±150ms)和偏移坐标(±5px)点击 28 | - 首页长按图标可自定义坐标 29 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | [简体中文](README.md) | English | [日本語](README_JP.md) 2 | # ArkTap 3 | ArkTap is a free software for Arknights. 4 | 5 | [Latest release](https://github.com/aistra0528/ArknightsTap/releases/latest) 6 | 7 | ## Features 8 | 9 | ### ARSS™ 10 | You can use it in game by a floating window. 11 | #### Recruit Guide 12 | Show possible operators in recruitment and help you choose the best combination of tags. 13 | #### Headhunt Counter 14 | Count the rolls of headhunt and show the possibility of 6★. 15 | #### Material Guide 16 | Recommend missions of elite materials. 17 | 18 | ### ARGS™ 19 | **Tap Version type 15 times in About to unlock this service** 20 | 21 | Tap the mission start button automatically. In that way you can put down your phone and do something more meaningful. -------------------------------------------------------------------------------- /README_JP.md: -------------------------------------------------------------------------------- 1 | [简体中文](README.md) | [English](README_EN.md) | 日本語 2 | # ArkTap 3 | ArkTapとは、株式会社Yostarのスマホゲーム、アークナイツのサードパーティサポートアプリです。 4 | 5 | [最新のリリース](https://github.com/aistra0528/ArknightsTap/releases/latest) 6 | 7 | ## 機能 8 | 9 | ### ARSS™ 10 | **※アクセス権限'他のアプリの上に重ねて表示'が必要** 11 | #### 公開求人シミュレータ 12 | 公開求人のシミュレータ。タグを選んで獲得できるキャラを確認できる機能です。 13 | #### スカウトカウンタ 14 | 15 | #### 素材周回オススメ 16 | 17 | ### ARGS™ 18 | **※'ArkTapについて'>'バージョンタイプ'を15回タップして起動** 19 | 20 | 自動周回。画面を自動タップして周回する機能です。 -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /debug/ 3 | /release/ 4 | *.apk 5 | *.aab 6 | *.bat -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | kotlin("android") 4 | } 5 | 6 | android { 7 | namespace = "com.icebem.akt" 8 | compileSdk = 33 9 | 10 | defaultConfig { 11 | applicationId = "com.icebem.akt" 12 | minSdk = 21 13 | targetSdk = 33 14 | versionCode = 69 15 | versionName = "3.0.3" 16 | resourceConfigurations += setOf("zh-rCN", "en", "ja", "in", "fr") 17 | } 18 | 19 | val signing = if (file("../signing.properties").exists()) { 20 | signingConfigs.create("release") { 21 | val props = `java.util`.Properties().apply { load(file("../signing.properties").reader()) } 22 | storeFile = file(props.getProperty("storeFile")) 23 | storePassword = props.getProperty("storePassword") 24 | keyAlias = props.getProperty("keyAlias") 25 | keyPassword = props.getProperty("keyPassword") 26 | } 27 | } else signingConfigs.getByName("debug") 28 | buildTypes { 29 | debug { 30 | applicationIdSuffix = ".luna" 31 | } 32 | release { 33 | isMinifyEnabled = true 34 | isShrinkResources = true 35 | signingConfig = signing 36 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") 37 | } 38 | } 39 | applicationVariants.configureEach { 40 | outputs.configureEach { 41 | (this as? com.android.build.gradle.internal.api.ApkVariantOutputImpl)?.outputFileName = "ArkTap-v$versionName.apk" 42 | } 43 | } 44 | compileOptions { 45 | sourceCompatibility(JavaVersion.VERSION_1_8) 46 | targetCompatibility(JavaVersion.VERSION_1_8) 47 | } 48 | kotlinOptions { 49 | jvmTarget = JavaVersion.VERSION_1_8.toString() 50 | } 51 | buildFeatures { 52 | viewBinding = true 53 | } 54 | dependenciesInfo { 55 | includeInApk = false 56 | includeInBundle = false 57 | } 58 | } 59 | 60 | dependencies { 61 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20") 62 | implementation("androidx.appcompat:appcompat:1.6.1") 63 | implementation("androidx.constraintlayout:constraintlayout:2.1.4") 64 | implementation("androidx.core:core-ktx:1.9.0") 65 | implementation("androidx.navigation:navigation-fragment-ktx:2.5.3") 66 | implementation("androidx.navigation:navigation-ui-ktx:2.5.3") 67 | implementation("androidx.preference:preference-ktx:1.2.0") 68 | implementation("com.google.android.flexbox:flexbox:3.0.0") 69 | implementation("com.google.android.material:material:1.8.0") 70 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 51 | 54 | 55 | 56 | 62 | 63 | 64 | 65 | 66 | 69 | 70 | 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/assets/contributors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "neko1da", 4 | "languages": [ 5 | "日本語" 6 | ], 7 | "networks": [ 8 | "GitHub" 9 | ] 10 | }, 11 | { 12 | "name": "op_satoshi", 13 | "languages": [ 14 | "日本語" 15 | ], 16 | "networks": [ 17 | "Twitter" 18 | ] 19 | }, 20 | { 21 | "name": "twiceYuan", 22 | "languages": [], 23 | "networks": [ 24 | "Telegram" 25 | ] 26 | }, 27 | { 28 | "name": "dwipaa11", 29 | "languages": [ 30 | "Indonesia" 31 | ], 32 | "networks": [ 33 | "Telegram" 34 | ] 35 | }, 36 | { 37 | "name": "AdityaTamamo", 38 | "languages": [ 39 | "Indonesia" 40 | ], 41 | "networks": [ 42 | "Telegram" 43 | ] 44 | }, 45 | { 46 | "name": "FhrShadow", 47 | "languages": [], 48 | "networks": [ 49 | "GitHub" 50 | ] 51 | }, 52 | { 53 | "name": "MathiusD", 54 | "languages": [ 55 | "Français" 56 | ], 57 | "networks": [ 58 | "GitHub", 59 | "GitLab" 60 | ] 61 | } 62 | ] -------------------------------------------------------------------------------- /app/src/main/assets/data/entry.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "entry.json", 4 | "compat": 29, 5 | "version": 69, 6 | "tag": "2023-05-01" 7 | }, 8 | { 9 | "name": "recruit.json", 10 | "compat": 29, 11 | "version": 20, 12 | "tag": "2023-07-06" 13 | }, 14 | { 15 | "name": "resolution.json", 16 | "compat": 29, 17 | "version": 57, 18 | "tag": "2023-07-06" 19 | }, 20 | { 21 | "name": "slogan.json", 22 | "compat": 49, 23 | "version": 11, 24 | "tag": "2023-05-03" 25 | }, 26 | { 27 | "name": "material.json", 28 | "compat": 61, 29 | "version": 10, 30 | "tag": "2023-03-21" 31 | } 32 | ] -------------------------------------------------------------------------------- /app/src/main/assets/data/gesture.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"name":"tap","x":0,"y":0}, 3 | {"name":"tap","x":0,"y":0}, 4 | {"name":"tap","x":0,"y":0} 5 | ] -------------------------------------------------------------------------------- /app/src/main/assets/data/resolution.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"width":480,"height":360,"blue_x":430,"blue_y":335,"red_x":415,"red_y":275}, 3 | {"width":1152,"height":720,"blue_x":1030,"blue_y":665,"red_x":1005,"red_y":555}, 4 | {"width":1480,"height":720,"blue_x":1340,"blue_y":655,"red_x":1145,"red_y":465}, 5 | {"width":1520,"height":720,"blue_x":1380,"blue_y":655,"red_x":1190,"red_y":465}, 6 | {"width":1600,"height":720,"blue_x":1470,"blue_y":655,"red_x":1265,"red_y":465}, 7 | {"width":1280,"height":768,"blue_x":1140,"blue_y":705,"red_x":1100,"red_y":595}, 8 | {"width":1280,"height":800,"blue_x":1140,"blue_y":735,"red_x":1100,"red_y":625}, 9 | {"width":1440,"height":810,"blue_x":1240,"blue_y":715,"red_x":1240,"red_y":715}, 10 | {"width":1920,"height":864,"blue_x":1755,"blue_y":790,"red_x":1520,"red_y":560}, 11 | {"width":1600,"height":900,"blue_x":1425,"blue_y":820,"red_x":1380,"red_y":630,"author":"Konecos"}, 12 | {"width":1972,"height":988,"blue_x":1675,"blue_y":870,"red_x":1675,"red_y":870}, 13 | {"width":2032,"height":1080,"blue_x":1735,"blue_y":950,"red_x":1735,"red_y":950}, 14 | {"width":2040,"height":1080,"blue_x":1750,"blue_y":955,"red_x":1750,"red_y":955}, 15 | {"width":2158,"height":1080,"blue_x":1835,"blue_y":950,"red_x":1835,"red_y":950}, 16 | {"width":2220,"height":1080,"blue_x":2015,"blue_y":985,"red_x":1720,"red_y":695}, 17 | {"width":2240,"height":1080,"blue_x":2035,"blue_y":985,"red_x":1735,"red_y":695}, 18 | {"width":2242,"height":1080,"blue_x":2030,"blue_y":985,"red_x":1745,"red_y":700}, 19 | {"width":2246,"height":1080,"blue_x":2050,"blue_y":985,"red_x":1750,"red_y":700}, 20 | {"width":2304,"height":1080,"blue_x":2100,"blue_y":985,"red_x":1800,"red_y":700}, 21 | {"width":2312,"height":1080,"blue_x":2115,"blue_y":985,"red_x":1805,"red_y":700}, 22 | {"width":2316,"height":1080,"blue_x":2120,"blue_y":985,"red_x":1810,"red_y":700}, 23 | {"width":2330,"height":1080,"blue_x":2125,"blue_y":985,"red_x":1825,"red_y":700}, 24 | {"width":2340,"height":1080,"blue_x":2125,"blue_y":985,"red_x":1835,"red_y":700}, 25 | {"width":2376,"height":1080,"blue_x":2180,"blue_y":985,"red_x":1870,"red_y":700}, 26 | {"width":2388,"height":1080,"blue_x":2195,"blue_y":985,"red_x":1885,"red_y":700}, 27 | {"width":2400,"height":1080,"blue_x":2195,"blue_y":985,"red_x":1895,"red_y":700}, 28 | {"width":2408,"height":1080,"blue_x":2200,"blue_y":985,"red_x":1900,"red_y":700}, 29 | {"width":2412,"height":1080,"blue_x":2205,"blue_y":985,"red_x":1910,"red_y":700}, 30 | {"width":2460,"height":1080,"blue_x":2255,"blue_y":985,"red_x":1965,"red_y":700}, 31 | {"width":2520,"height":1080,"blue_x":2315,"blue_y":985,"red_x":2015,"red_y":700}, 32 | {"width":2636,"height":1080,"blue_x":2430,"blue_y":985,"red_x":2105,"red_y":700}, 33 | {"width":2640,"height":1080,"blue_x":2435,"blue_y":1005,"red_x":2108,"red_y":700}, 34 | {"width":2480,"height":1116,"blue_x":2270,"blue_y":1040,"red_x":1965,"red_y":720}, 35 | {"width":2376,"height":1152,"blue_x":2170,"blue_y":1005,"red_x":1860,"red_y":715,"raw_height":1104}, 36 | {"width":2000,"height":1200,"blue_x":1785,"blue_y":1100,"red_x":1720,"red_y":930}, 37 | {"width":2640,"height":1200,"blue_x":2430,"blue_y":1095,"red_x":2080,"red_y":775}, 38 | {"width":2712,"height":1220,"blue_x":2480,"blue_y":1135,"red_x":2145,"red_y":780}, 39 | {"width":2688,"height":1224,"blue_x":2460,"blue_y":1140,"red_x":2120,"red_y":790}, 40 | {"width":2700,"height":1228,"blue_x":2465,"blue_y":1120,"red_x":2130,"red_y":790}, 41 | {"width":2676,"height":1236,"blue_x":2325,"blue_y":1150,"red_x":2030,"red_y":800}, 42 | {"width":2772,"height":1240,"blue_x":2540,"blue_y":1155,"red_x":2195,"red_y":795}, 43 | {"width":2800,"height":1260,"blue_x":2565,"blue_y":1175,"red_x":2215,"red_y":810}, 44 | {"width":2560,"height":1316,"blue_x":2185,"blue_y":1165,"red_x":2185,"red_y":1165}, 45 | {"width":2595,"height":1440,"blue_x":2930,"blue_y":1340,"red_x":2530,"red_y":930,"raw_width":3200}, 46 | {"width":2772,"height":1344,"blue_x":2525,"blue_y":1175,"red_x":2170,"red_y":830,"raw_height":1288}, 47 | {"width":2960,"height":1440,"blue_x":2700,"blue_y":1315,"red_x":2290,"red_y":930}, 48 | {"width":3088,"height":1440,"blue_x":2810,"blue_y":1340,"red_x":2415,"red_y":930}, 49 | {"width":3168,"height":1440,"blue_x":2910,"blue_y":1315,"red_x":2495,"red_y":930}, 50 | {"width":3200,"height":1440,"blue_x":2925,"blue_y":1315,"red_x":2530,"red_y":930}, 51 | {"width":3216,"height":1440,"blue_x":2940,"blue_y":1315,"red_x":2550,"red_y":930}, 52 | {"width":2560,"height":1600,"blue_x":2290,"blue_y":1500,"red_x":2210,"red_y":850}, 53 | {"width":3840,"height":1644,"blue_x":3530,"blue_y":1500,"red_x":3080,"red_y":1060}, 54 | {"width":2800,"height":1752,"blue_x":2505,"blue_y":1645,"red_x":2420,"red_y":930}, 55 | {"width":2880,"height":1800,"blue_x":2575,"blue_y":1690,"red_x":2490,"red_y":955}, 56 | {"width":3840,"height":2160,"blue_x":3315,"blue_y":1910,"red_x":3315,"red_y":1910}, 57 | {"width":1024,"height":576,"blue_x":930,"blue_y":520,"red_x":920,"red_y":510}, 58 | {"width":1440,"height":576,"blue_x":1330,"blue_y":520,"red_x":1130,"red_y":510}, 59 | {"width":1280,"height":720,"blue_x":1100,"blue_y":670,"red_x":1100,"red_y":650}, 60 | {"width":1440,"height":720,"blue_x":1330,"blue_y":670,"red_x":1200,"red_y":650}, 61 | {"width":1520,"height":720,"blue_x":1300,"blue_y":655,"red_x":1250,"red_y":620,"author":"twiceYuan"}, 62 | {"width":1560,"height":720,"blue_x":1470,"blue_y":670,"red_x":1230,"red_y":650}, 63 | {"width":1024,"height":768,"blue_x":920,"blue_y":720,"red_x":880,"red_y":580}, 64 | {"width":1920,"height":1080,"blue_x":1650,"blue_y":1000,"red_x":1650,"red_y":960}, 65 | {"width":2160,"height":1080,"blue_x":2000,"blue_y":1000,"red_x":1800,"red_y":960}, 66 | {"width":2232,"height":1080,"blue_x":2030,"blue_y":1000,"red_x":1810,"red_y":960}, 67 | {"width":2244,"height":1080,"blue_x":2050,"blue_y":1000,"red_x":1830,"red_y":960}, 68 | {"width":2248,"height":1080,"blue_x":2050,"blue_y":1000,"red_x":1830,"red_y":960}, 69 | {"width":2280,"height":1080,"blue_x":2090,"blue_y":1000,"red_x":1840,"red_y":960}, 70 | {"width":2310,"height":1080,"blue_x":2110,"blue_y":1000,"red_x":1850,"red_y":960}, 71 | {"width":2560,"height":1096,"blue_x":2350,"blue_y":1030,"red_x":1990,"red_y":970}, 72 | {"width":2400,"height":1176,"blue_x":2110,"blue_y":1050,"red_x":1990,"red_y":1015}, 73 | {"width":1920,"height":1200,"blue_x":1730,"blue_y":1110,"red_x":1660,"red_y":930}, 74 | {"width":2560,"height":1440,"blue_x":2200,"blue_y":1330,"red_x":2200,"red_y":1280}, 75 | {"width":2880,"height":1440,"blue_x":2660,"blue_y":1330,"red_x":2400,"red_y":1280}, 76 | {"width":2960,"height":1440,"blue_x":2800,"blue_y":1330,"red_x":2430,"red_y":1280}, 77 | {"width":3040,"height":1440,"blue_x":2810,"blue_y":1330,"red_x":2450,"red_y":1280}, 78 | {"width":3120,"height":1440,"blue_x":2940,"blue_y":1330,"red_x":2470,"red_y":1280}, 79 | {"width":2048,"height":1536,"blue_x":1870,"blue_y":1430,"red_x":1760,"red_y":1130} 80 | ] -------------------------------------------------------------------------------- /app/src/main/assets/data/slogan.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"name":"阿米娅","slogan":"博士,您还有许多事情需要处理。现在还不能休息哦。"}, 3 | {"name":"白面鸮","slogan":"......系统进入睡眠模式。"}, 4 | {"name":"拉普兰德","slogan":"睡吧,至少现在,你还能做个美梦......"}, 5 | {"name":"银灰","slogan":"“——天空似乎暗了下来,要下雪了——”"}, 6 | {"name":"夜莺","slogan":"......于睡梦中,您是否,也会成为一只自由的飞鸟呢?"}, 7 | {"name":"伊芙利特","slogan":"你这家伙,把我晾在一边一个人睡大觉,胆子很大啊!"}, 8 | {"name":"刻俄柏","slogan":"博士呼噜呼噜的样子还挺有意思的。"}, 9 | {"name":"惊蛰","slogan":"竟然连自己的身体状态都掌控不好......太懈怠了!趴在这里睡觉,难道还等着我给你盖上毯子吗?......没下次了。"}, 10 | {"name":"巫恋","slogan":"安睡吧♪安睡吧♪被梦湮没吧♪"}, 11 | {"name":"空弦","slogan":"好像听见了钟声......嗯,错觉吧。"}, 12 | {"name":"暴雨","slogan":"(有点想看......博士的睡脸)"}, 13 | {"name":"赤冬","slogan":"这角落挺凉快啊,让让,我也躺下歇一歇。"}, 14 | {"name":"夕","slogan":"梦如人生,梦入长卷。人这一睡,会睡过几个千年呢?"}, 15 | {"name":"浊心斯卡蒂","slogan":"梦......你会有怎样一个梦呢?你现在身处何方?那里......会不会也是一个梦呢?"}, 16 | {"name":"贝娜","slogan":"“好好休息。博士。”别管他了,我们出去玩吧。“好的。”"}, 17 | {"name":"绮良","slogan":"等等,现在先别和我说话,还差一点......再吃一招对面就完蛋了!——啊!好耶稀有素材掉落了!"}, 18 | {"name":"帕拉斯","slogan":"我习惯了站着不动思考。有时候啊,也会被大家突然戳一戳,看看睡着了没有。"}, 19 | {"name":"羽毛笔","slogan":"博士面罩下面是什么样的呢,悄悄看看吧......"}, 20 | {"name":"凯尔希","slogan":"你醒了吗,还是还在梦中?"}, 21 | {"name":"桑葚","slogan":"博士,博士?打、打扰了,稍微起来一下,垫上这个垫子再睡吧?现在这样睡下去,报告书上的字会印在脸上的......"}, 22 | {"name":"琴柳","slogan":"博士,看到您现在的模样,我总会想起那些躲在罗德岛办事处里偷懒的日子......阳光,牌局,还有大家。啊,真的好怀念。"}, 23 | {"name":"蜜莓","slogan":"博士,你睡着了吗?......唔,完全没反应,看来真的睡了。好机会!让我看看博士把零食都藏在哪儿了......"}, 24 | {"name":"耶拉","slogan":"哎呀,博士的睡相真差......去打盆水放着好了,这样醒来可以洗洗脸。"}, 25 | {"name":"极光","slogan":"博士,我的外套,给你。趴着睡觉,容易着凉。"}, 26 | {"name":"老鲤","slogan":"与其忙忙碌碌,倒不如得闲饮茶。嗳,博士,你这儿的茶叶挺不错啊。"}, 27 | {"name":"令","slogan":"云峦波涛,千里枯路,江山故人我,晚秋行舟。"}, 28 | {"name":"澄闪","slogan":"接地......好,这下就不会炸毛了。趁博士睡着,我也偷个懒。"}, 29 | {"name":"菲亚梅塔","slogan":"居然站着睡着了......装得还挺像那么回事的,比当年学校里那群上课偷偷睡觉的家伙强。"}, 30 | {"name":"号角","slogan":"......见过了那么多惨象,你是怎么还能睡着的?......如果我也能这样,只是合上双眼,我会感觉好一些吗?"}, 31 | {"name":"掠风","slogan":"睡着了哎?好安静......汪呜!——噢、您醒了啊,博士?"}, 32 | {"name":"流明","slogan":"博士,博士?就这么睡着会受凉的,我去给您拿条毯子。灯光也为您调暗一些,没问题吧?"}, 33 | {"name":"艾丽妮","slogan":"危机当前,还能倒头就睡?也不知道该不该羡慕你......算了,就让你休息一会,我在这里等着。"}, 34 | {"name":"埃拉托","slogan":"博士,博士?睡着了啊......本来还准备了一首曲子想弹给你听呢......"}, 35 | {"name":"濯尘芙蓉","slogan":"博士虽然在工作上很可靠,但平时就像个孩子呢。又趴在桌子上睡着了,说过多少遍,这样对脊椎不好,而且很容易感冒的......唉,如果哪天我不在了,博士能照顾好自己吗?"}, 36 | {"name":"黑键","slogan":"在这种地方也能睡着?啧,这种时候就该轮到助理工作了吧,麻烦死了——啊,写错字了。不管了不管了,让我听听博士的耳机里在放什么音乐......"}, 37 | {"name":"至简","slogan":"嗯,如此有违常规的睡姿,如此复杂但又稳定的受力结构......神奇,真的不会得颈椎病吗?"}, 38 | {"name":"晓歌","slogan":"一手培养我的人都不敢在我面前安心入睡,你......这么信任我?"}, 39 | {"name":"鸿雪","slogan":"博士,您睡了吗?没睡?没睡也没关系,如果您打算长时间保持同一种姿势,我或许可以为您画一张钢笔素描。"}, 40 | {"name":"玛恩纳","slogan":"没有灯光的荒野......"}, 41 | {"name":"海沫","slogan":"......在你的梦里,是不是也会见到那些,从你生命中悄然离你而去的人。"}, 42 | {"name":"达格达","slogan":"守夜可是塔楼骑士的职责。博士,请好好休息。"}, 43 | {"name":"明椒","slogan":"好闲啊......我也来织点什么吧,像我这样的小包怎么样?很实用哦!"}, 44 | {"name":"子月","slogan":"睡着了?那没我的事了?阿涅塞,走,去外面玩了。"}, 45 | {"name":"缄默德克萨斯","slogan":"休息时间。这里不会有阴影中的杀手,巷子里的狼。"}, 46 | {"name":"和弦","slogan":"哼哼~指甲涂个什么新花样好呢?"}, 47 | {"name":"焰影苇草","slogan":"就这样,什么也不用说......你的身边,总是如此安宁。"}, 48 | {"name":"火哨","slogan":"呼啊......好无聊啊,摆个榴弹塔吧——欸,你其实没睡?!不不不,这是空包弹,空包弹!"}, 49 | {"name":"林","slogan":"......你疲惫的样子,是不是也不该让太多人看见?"}, 50 | {"name":"重岳","slogan":"......来去春景,怅然秋心。"}, 51 | {"name":"U-Official","slogan":"你好,是来找博士的吗?......完全不打扰哦,博士睡了,我只是在干吃他的泡面而已。要来一块吗?"}, 52 | {"name":"休谟斯","slogan":"有什么事明天再说,今天食堂肉排不限量供应,我得赶紧过去!"}, 53 | {"name":"摩根","slogan":"......哎呀,毫无防备的样子。要不要在你脸上画点什么呢?"}, 54 | {"name":"洋灰","slogan":"非施工时段,大家好好休息。"}, 55 | {"name":"伊内丝","slogan":"......你的梦比我想象中的更平静。"}, 56 | {"name":"霍尔海雅","slogan":"你的耳朵红了,好敏感啊,呼......哎呀,更红了。呵呵,不可以乱动哦,现在不是还在工作中吗?"}, 57 | {"name":"缪尔赛思","slogan":"你是说,把工作时间和行程的决定权交给我吗,那就意味着,我在备忘录上写什么,你就得做什么了哦,博士。哎呀,现在反悔已经来不及了,呼呼~"}, 58 | {"name":"缪尔赛思","slogan":"嘴唇是不是有些干?......好像还有些脱皮了,平常一定要多喝水啊。唉,我的润唇膏给你吧,之后买一支还给我就行。我只用这个牌子的,薄荷味,可别买错了,好吗?"}, 59 | {"name":"缪尔赛思","slogan":"工作的时候分神可不是个好习惯。"}, 60 | {"name":"缪尔赛思","slogan":"你赠送的礼物,我一定会好好保存的,作为回报,就一起去影院吧。"} 61 | ] -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/ArkApp.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt 2 | 3 | import android.app.Application 4 | import com.icebem.akt.util.ArkIO 5 | 6 | class ArkApp : Application() { 7 | override fun onCreate() { 8 | super.onCreate() 9 | app = this 10 | clearCache() 11 | } 12 | 13 | private fun clearCache() = ArkIO.clearDirectory(cacheDir.path) 14 | 15 | companion object { 16 | lateinit var app: ArkApp private set 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/adapter/MaterialAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.adapter 2 | 3 | import android.annotation.SuppressLint 4 | import android.view.ViewGroup 5 | import android.widget.ImageView 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.icebem.akt.R 8 | import com.icebem.akt.model.MaterialInfo 9 | import com.icebem.akt.overlay.OverlayToast 10 | import com.icebem.akt.util.ArkPref 11 | import com.icebem.akt.util.Resolution 12 | 13 | class MaterialAdapter : RecyclerView.Adapter() { 14 | companion object { 15 | const val COUNT_SPAN = 6 16 | 17 | private const val RES_START_MTL = "mtl_" 18 | private const val RES_TYPE = "mipmap" 19 | private val mtlId = intArrayOf(30011, 30021, 30031, 30041, 30051, 30061, 30012, 30022, 30032, 30042, 30052, 30062, 30013, 30023, 30033, 30043, 30053, 30063, 30014, 30024, 30034, 30044, 30054, 30064, 30073, 30074, 30083, 30084, 30093, 30094, 30103, 30104, 31013, 31014, 31023, 31024, 31033, 31034, 31043, 31044, 31053, 31054, 31063, 31064) 20 | } 21 | 22 | class ViewHolder(itemView: ImageView) : RecyclerView.ViewHolder(itemView) 23 | 24 | private val infos: Array = MaterialInfo.array 25 | 26 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 27 | val view = ImageView(parent.context) 28 | var size = view.context.resources.getDimensionPixelOffset(R.dimen.control_padding) shl 1 29 | size = (Resolution.physicalHeight - size) / COUNT_SPAN 30 | view.layoutParams = ViewGroup.LayoutParams(size, size) 31 | return ViewHolder(view) 32 | } 33 | 34 | @SuppressLint("DiscouragedApi") 35 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 36 | val info = findMaterialById(mtlId[position]) ?: return 37 | val view = holder.itemView as ImageView 38 | view.setImageResource(view.resources.getIdentifier(RES_START_MTL + info.id, RES_TYPE, view.context.packageName)) 39 | view.setOnClickListener { 40 | val str = buildString { 41 | if (info.items.isEmpty()) { 42 | append(info.getName(ArkPref.translationIndex)) 43 | } else { 44 | append(it.context.getString(R.string.tip_material_workshop, info.getName(ArkPref.translationIndex))) 45 | for (item in info.items) { 46 | val mtl = findMaterialById(item.id) ?: break 47 | appendLine() 48 | append(it.context.getString(R.string.tip_material_item, mtl.getName(ArkPref.translationIndex), item.quantity)) 49 | } 50 | } 51 | if (info.stages.isNotEmpty()) { 52 | for (mission in info.stages) { 53 | appendLine() 54 | val sanity = mission.sanity 55 | val frequency = mission.frequency 56 | append(it.context.getString(R.string.tip_material_mission, mission.mission, frequency * 100, sanity / frequency)) 57 | } 58 | } 59 | } 60 | OverlayToast.show(str, OverlayToast.LENGTH_LONG) 61 | } 62 | } 63 | 64 | private fun findMaterialById(id: Int): MaterialInfo? { 65 | for (info in infos) if (info.id == id) return info 66 | return null 67 | } 68 | 69 | override fun getItemCount(): Int = mtlId.size 70 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/model/ContributorInfo.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.model 2 | 3 | import android.content.res.Resources 4 | import com.icebem.akt.R 5 | import com.icebem.akt.util.ArkContributors 6 | import org.json.JSONException 7 | import org.json.JSONObject 8 | import java.io.IOException 9 | 10 | class ContributorInfo private constructor(obj: JSONObject) { 11 | companion object { 12 | private const val KEY_NAME = "name" 13 | private const val KEY_LANGUAGES = "languages" 14 | private const val KEY_NETWORKS = "networks" 15 | 16 | @get:Throws(IOException::class, JSONException::class) 17 | val array: Array 18 | get() { 19 | val array = ArkContributors.getContributorsData() 20 | return mutableListOf().apply { 21 | for (i in 0 until array.length()) add(ContributorInfo(array.getJSONObject(i))) 22 | }.toTypedArray() 23 | } 24 | } 25 | 26 | private val name: String = obj.getString(KEY_NAME) 27 | private val languages: Array = mutableListOf().apply { 28 | val array = obj.getJSONArray(KEY_LANGUAGES) 29 | for (i in 0 until array.length()) add(array.getString(i)) 30 | }.toTypedArray() 31 | private val networks: Array = mutableListOf().apply { 32 | val array = obj.getJSONArray(KEY_NETWORKS) 33 | for (i in 0 until array.length()) add(array.getString(i)) 34 | }.toTypedArray() 35 | 36 | fun toLocalizedString(resources: Resources): String = buildString { 37 | if (networks.isNotEmpty()) append(networks.joinToString(separator = "/", postfix = " @")) 38 | append(name) 39 | append(" - ") 40 | append(resources.getString(R.string.contributor)) 41 | if (languages.isNotEmpty()) { 42 | append(" & ") 43 | append(resources.getString(R.string.translator)) 44 | append(languages.joinToString(prefix = " (", postfix = ")")) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/model/HeadhuntCounter.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.model 2 | 3 | import android.widget.TextView 4 | import com.icebem.akt.R 5 | import com.icebem.akt.databinding.OverlayCounterBinding 6 | import com.icebem.akt.util.ArkPref 7 | 8 | class HeadhuntCounter(binding: OverlayCounterBinding) { 9 | private var limited: Boolean = ArkPref.getHeadhuntCount(true) > 0 10 | 11 | init { 12 | binding.txtCounterTitle.setText(if (limited) R.string.counter_limited else R.string.counter_normal) 13 | binding.actionToggle.setOnClickListener { toggle(binding.txtCounterTitle, binding.txtCounterTips) } 14 | binding.actionMinus.run { 15 | setOnClickListener { update(binding.txtCounterTips, ArkPref.getHeadhuntCount(limited), -1) } 16 | setOnLongClickListener { update(binding.txtCounterTips, 0, 0) } 17 | } 18 | binding.actionPlus.run { 19 | setOnClickListener { update(binding.txtCounterTips, ArkPref.getHeadhuntCount(limited), 1) } 20 | setOnLongClickListener { update(binding.txtCounterTips, ArkPref.getHeadhuntCount(limited), 10) } 21 | } 22 | update(binding.txtCounterTips, ArkPref.getHeadhuntCount(limited), 0) 23 | } 24 | 25 | private fun toggle(title: TextView, tips: TextView) { 26 | limited = !limited 27 | title.setText(if (limited) R.string.counter_limited else R.string.counter_normal) 28 | update(tips, ArkPref.getHeadhuntCount(limited), 0) 29 | } 30 | 31 | private fun update(tip: TextView, count: Int, delta: Int): Boolean { 32 | var mCount = count 33 | mCount += delta 34 | if (mCount < 0) mCount += 99 else if (mCount >= 99) mCount -= 99 35 | ArkPref.setHeadhuntCount(mCount, limited) 36 | var possibility = 2 37 | if (mCount > 49) possibility += mCount - 49 shl 1 38 | tip.text = tip.context.getString(R.string.tip_counter_default, mCount, possibility) 39 | return true 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/model/MaterialInfo.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.model 2 | 3 | import com.icebem.akt.util.ArkData 4 | import org.json.JSONException 5 | import org.json.JSONObject 6 | import java.io.IOException 7 | 8 | class MaterialInfo private constructor(obj: JSONObject) { 9 | companion object { 10 | private const val KEY_ID = "id" 11 | private const val KEY_NAME = "name" 12 | private const val KEY_NAME_CN = "nameCN" 13 | private const val KEY_NAME_TW = "nameTW" 14 | private const val KEY_NAME_JP = "nameJP" 15 | private const val KEY_NAME_KR = "nameKR" 16 | private const val KEY_STAGES = "stages" 17 | private const val KEY_WORKSHOP = "workshop" 18 | 19 | @get:Throws(IOException::class, JSONException::class) 20 | val array: Array 21 | get() { 22 | val array = ArkData.getMaterialData() 23 | return mutableListOf().apply { 24 | for (i in 0 until array.length()) add(MaterialInfo(array.getJSONObject(i))) 25 | }.toTypedArray() 26 | } 27 | } 28 | 29 | val id: Int = obj.getInt(KEY_ID) 30 | private val name: String = obj.getString(KEY_NAME) 31 | private val nameCN: String = obj.getString(KEY_NAME_CN) 32 | private val nameTW: String = obj.getString(KEY_NAME_TW) 33 | private val nameJP: String = obj.getString(KEY_NAME_JP) 34 | private val nameKR: String = obj.getString(KEY_NAME_KR) 35 | val stages: Array = mutableListOf().apply { 36 | val array = obj.getJSONArray(KEY_STAGES) 37 | for (i in 0 until array.length()) add(Mission(array.getJSONObject(i))) 38 | }.toTypedArray() 39 | val items: Array = mutableListOf().apply { 40 | val array = obj.getJSONArray(KEY_WORKSHOP) 41 | for (i in 0 until array.length()) add(ShopItem(array.getJSONObject(i))) 42 | }.toTypedArray() 43 | 44 | fun getName(index: Int): String = when (index) { 45 | ArkData.INDEX_EN -> name 46 | ArkData.INDEX_TW -> nameTW 47 | ArkData.INDEX_JP -> nameJP 48 | ArkData.INDEX_KR -> nameKR 49 | else -> nameCN 50 | } 51 | 52 | class Mission internal constructor(obj: JSONObject) { 53 | companion object { 54 | private const val KEY_MISSION = "mission" 55 | private const val KEY_SANITY = "sanity" 56 | private const val KEY_FREQUENCY = "frequency" 57 | } 58 | 59 | val mission: String = obj.getString(KEY_MISSION) 60 | val sanity: Int = obj.getInt(KEY_SANITY) 61 | val frequency: Float = obj.getDouble(KEY_FREQUENCY).toFloat() 62 | } 63 | 64 | class ShopItem internal constructor(obj: JSONObject) { 65 | companion object { 66 | private const val KEY_QUANTITY = "quantity" 67 | } 68 | 69 | val id: Int = obj.getInt(KEY_ID) 70 | val quantity: Int = obj.getInt(KEY_QUANTITY) 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/model/OperatorInfo.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.model 2 | 3 | import com.icebem.akt.util.ArkData 4 | import org.json.JSONException 5 | import org.json.JSONObject 6 | import java.io.IOException 7 | 8 | internal class OperatorInfo private constructor(obj: JSONObject) { 9 | companion object { 10 | private const val KEY_STAR = "star" 11 | private const val KEY_NAME = "name" 12 | private const val KEY_NAME_CN = "nameCN" 13 | private const val KEY_NAME_TW = "nameTW" 14 | private const val KEY_NAME_JP = "nameJP" 15 | private const val KEY_NAME_KR = "nameKR" 16 | private const val KEY_TYPE = "type" 17 | private const val KEY_TAGS = "tags" 18 | 19 | @get:Throws(IOException::class, JSONException::class) 20 | val array: Array 21 | get() { 22 | val array = ArkData.getRecruitData() 23 | return mutableListOf().apply { 24 | for (i in 0 until array.length()) add(OperatorInfo(array.getJSONObject(i))) 25 | }.toTypedArray() 26 | } 27 | } 28 | 29 | val star: Int = obj.getInt(KEY_STAR) 30 | private val name: String = obj.getString(KEY_NAME) 31 | private val nameCN: String = obj.getString(KEY_NAME_CN) 32 | private val nameTW: String = obj.getString(KEY_NAME_TW) 33 | private val nameJP: String = obj.getString(KEY_NAME_JP) 34 | private val nameKR: String = obj.getString(KEY_NAME_KR) 35 | val type: String = obj.getString(KEY_TYPE) 36 | val tags: Array = mutableListOf().apply { 37 | val array = obj.getJSONArray(KEY_TAGS) 38 | for (i in 0 until array.length()) add(array.getString(i)) 39 | }.toTypedArray() 40 | 41 | fun containsTag(tag: String): Boolean = tag in tags 42 | 43 | fun getName(index: Int): String = when (index) { 44 | ArkData.INDEX_EN -> name 45 | ArkData.INDEX_TW -> nameTW 46 | ArkData.INDEX_JP -> nameJP 47 | ArkData.INDEX_KR -> nameKR 48 | else -> nameCN 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/model/RecruitTag.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.model 2 | 3 | import android.util.SparseArray 4 | import com.icebem.akt.R 5 | import com.icebem.akt.util.ArkData 6 | 7 | internal object RecruitTag { 8 | private val STAR_1 = arrayOf("1★", "1★", "1★", "★1", "1★") 9 | private val STAR_2 = arrayOf("2★", "2★", "2★", "★2", "2★") 10 | private val STAR_3 = arrayOf("3★", "3★", "3★", "★3", "3★") 11 | private val STAR_4 = arrayOf("4★", "4★", "4★", "★4", "4★") 12 | private val STAR_5 = arrayOf("5★", "5★", "5★", "★5", "5★") 13 | private val STAR_6 = arrayOf("6★", "6★", "6★", "★6", "6★") 14 | val QUALIFICATION_1 = arrayOf("Robot", "支援机械", "支援機械", "ロボット", "로봇") 15 | private val QUALIFICATION_2 = arrayOf("Starter", "新手", "新手", "初期", "신입") 16 | val QUALIFICATION_5 = arrayOf("Senior Operator", "资深干员", "資深幹員", "エリート", "특별 채용") 17 | val QUALIFICATION_6 = arrayOf("Top Operator", "高级资深干员", "高級資深幹員", "上級エリート", "고급 특별 채용") 18 | private val POSITION_MELEE = arrayOf("Melee", "近战位", "近戰位", "近距離", "근거리") 19 | private val POSITION_RANGED = arrayOf("Ranged", "远程位", "遠程位", "遠距離", "원거리") 20 | private val TYPE_VANGUARD = arrayOf("Vanguard", "先锋干员", "先鋒幹員", "先鋒タイプ", "뱅가드") 21 | private val TYPE_SNIPER = arrayOf("Sniper", "狙击干员", "狙擊幹員", "狙撃タイプ", "스나이퍼") 22 | private val TYPE_GUARD = arrayOf("Guard", "近卫干员", "近衛幹員", "前衛タイプ", "가드") 23 | private val TYPE_CASTER = arrayOf("Caster", "术师干员", "術師幹員", "術師タイプ", "캐스터") 24 | private val TYPE_DEFENDER = arrayOf("Defender", "重装干员", "重裝幹員", "重装タイプ", "디펜더") 25 | private val TYPE_MEDIC = arrayOf("Medic", "医疗干员", "醫療幹員", "医療タイプ", "메딕") 26 | private val TYPE_SPECIALIST = arrayOf("Specialist", "特种干员", "特種幹員", "特殊タイプ", "스페셜리스트") 27 | private val TYPE_SUPPORTER = arrayOf("Supporter", "辅助干员", "輔助幹員", "補助タイプ", "서포터") 28 | private val AFFIX_SURVIVAL = arrayOf("Survival", "生存", "生存", "生存", "생존형") 29 | private val AFFIX_AOE = arrayOf("AoE", "群攻", "群攻", "範囲攻撃", "범위공격") 30 | private val AFFIX_SLOW = arrayOf("Slow", "减速", "減速", "減速", "감속") 31 | private val AFFIX_HEALING = arrayOf("Healing", "治疗", "治療", "治療", "힐링") 32 | private val AFFIX_DPS = arrayOf("DPS", "输出", "輸出", "火力", "딜러") 33 | private val AFFIX_DEFENSE = arrayOf("Defense", "防护", "防護", "防御", "방어형") 34 | private val AFFIX_RECOVERY = arrayOf("DP-Recovery", "费用回复", "費用回復", "COST回復", "코스트+") 35 | private val AFFIX_REDEPLOY = arrayOf("Fast-Redeploy", "快速复活", "快速復活", "高速再配置", "쾌속부활") 36 | private val AFFIX_DEBUFF = arrayOf("Debuff", "削弱", "削弱", "弱化", "디버프") 37 | private val AFFIX_SUPPORT = arrayOf("Support", "支援", "支援", "支援", "지원") 38 | private val AFFIX_SHIFT = arrayOf("Shift", "位移", "位移", "強制移動", "강제이동") 39 | private val AFFIX_SUMMON = arrayOf("Summon", "召唤", "召喚", "召喚", "소환") 40 | private val AFFIX_NUKER = arrayOf("Nuker", "爆发", "爆發", "爆発力", "누커") 41 | private val AFFIX_CONTROL = arrayOf("Crowd-Control", "控场", "控場", "牽制", "제어형") 42 | private val TAG_ARRAY = arrayOf(QUALIFICATION_2, POSITION_MELEE, POSITION_RANGED, TYPE_VANGUARD, TYPE_SNIPER, TYPE_GUARD, TYPE_CASTER, TYPE_DEFENDER, TYPE_MEDIC, TYPE_SPECIALIST, TYPE_SUPPORTER, AFFIX_SURVIVAL, AFFIX_AOE, AFFIX_SLOW, AFFIX_HEALING, AFFIX_DPS, AFFIX_DEFENSE, AFFIX_RECOVERY, AFFIX_REDEPLOY, AFFIX_DEBUFF, AFFIX_SUPPORT, AFFIX_SHIFT, AFFIX_SUMMON, AFFIX_NUKER, AFFIX_CONTROL) 43 | 44 | val array: SparseArray> 45 | get() = SparseArray>().apply { 46 | put(R.id.tag_star_1, STAR_1) 47 | put(R.id.tag_star_2, STAR_2) 48 | put(R.id.tag_star_3, STAR_3) 49 | put(R.id.tag_star_4, STAR_4) 50 | put(R.id.tag_star_5, STAR_5) 51 | put(R.id.tag_star_6, STAR_6) 52 | put(R.id.tag_qualification_1, QUALIFICATION_1) 53 | put(R.id.tag_qualification_2, QUALIFICATION_2) 54 | put(R.id.tag_qualification_5, QUALIFICATION_5) 55 | put(R.id.tag_qualification_6, QUALIFICATION_6) 56 | put(R.id.tag_position_melee, POSITION_MELEE) 57 | put(R.id.tag_position_ranged, POSITION_RANGED) 58 | put(R.id.tag_type_vanguard, TYPE_VANGUARD) 59 | put(R.id.tag_type_sniper, TYPE_SNIPER) 60 | put(R.id.tag_type_guard, TYPE_GUARD) 61 | put(R.id.tag_type_caster, TYPE_CASTER) 62 | put(R.id.tag_type_defender, TYPE_DEFENDER) 63 | put(R.id.tag_type_medic, TYPE_MEDIC) 64 | put(R.id.tag_type_specialist, TYPE_SPECIALIST) 65 | put(R.id.tag_type_supporter, TYPE_SUPPORTER) 66 | put(R.id.tag_affix_survival, AFFIX_SURVIVAL) 67 | put(R.id.tag_affix_aoe, AFFIX_AOE) 68 | put(R.id.tag_affix_slow, AFFIX_SLOW) 69 | put(R.id.tag_affix_healing, AFFIX_HEALING) 70 | put(R.id.tag_affix_dps, AFFIX_DPS) 71 | put(R.id.tag_affix_defense, AFFIX_DEFENSE) 72 | put(R.id.tag_affix_recovery, AFFIX_RECOVERY) 73 | put(R.id.tag_affix_redeploy, AFFIX_REDEPLOY) 74 | put(R.id.tag_affix_debuff, AFFIX_DEBUFF) 75 | put(R.id.tag_affix_support, AFFIX_SUPPORT) 76 | put(R.id.tag_affix_shift, AFFIX_SHIFT) 77 | put(R.id.tag_affix_summon, AFFIX_SUMMON) 78 | put(R.id.tag_affix_nuker, AFFIX_NUKER) 79 | put(R.id.tag_affix_control, AFFIX_CONTROL) 80 | } 81 | 82 | fun getTagName(tagName: String, index: Int): String { 83 | if (index != ArkData.INDEX_EN) { 84 | for (array in TAG_ARRAY) { 85 | if (tagName == array[ArkData.INDEX_EN]) return array[index] 86 | } 87 | } 88 | return tagName 89 | } 90 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/overlay/OverlayToast.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ArkTap. 3 | * Copyright (C) 2019-2021 艾星Aistra 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.icebem.akt.overlay 19 | 20 | import android.annotation.SuppressLint 21 | import androidx.appcompat.view.ContextThemeWrapper 22 | import androidx.core.widget.TextViewCompat 23 | import com.google.android.material.textview.MaterialTextView 24 | import com.icebem.akt.ArkApp.Companion.app 25 | import com.icebem.akt.R 26 | import com.icebem.akt.util.Resolution 27 | 28 | /** 29 | * 悬浮吐司 30 | */ 31 | object OverlayToast { 32 | const val LENGTH_INDEFINITE = 0L 33 | const val LENGTH_SHORT = 2000L 34 | const val LENGTH_LONG = 3000L 35 | private val removal = Runnable { toast?.remove() } 36 | 37 | @SuppressLint("StaticFieldLeak") 38 | private var toast: OverlayView? = null 39 | 40 | fun show(text: String, duration: Long) { 41 | view.removeCallbacks(removal) 42 | removal.run() 43 | view.text = text 44 | toast?.show() 45 | if (duration > LENGTH_INDEFINITE) view.postDelayed(removal, duration) 46 | } 47 | 48 | fun show(resId: Int, duration: Long) = show(app.getString(resId), duration) 49 | 50 | private val view: MaterialTextView 51 | get() = toast?.view as? MaterialTextView 52 | ?: MaterialTextView(ContextThemeWrapper(app, R.style.Theme_MaterialComponents_Light)).apply { 53 | TextViewCompat.setTextAppearance(this, R.style.TextAppearance_MaterialComponents_Body2) 54 | val padding = context.resources.getDimensionPixelOffset(R.dimen.view_padding) 55 | setPadding(padding, padding, padding, padding) 56 | setBackgroundResource(R.drawable.bg_toast) 57 | setOnClickListener { 58 | it.removeCallbacks(removal) 59 | removal.run() 60 | } 61 | }.also { 62 | toast = OverlayView(it).apply { setRelativePosition(0, Resolution.physicalHeight shr 2) } 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/overlay/OverlayView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ArkTap. 3 | * Copyright (C) 2019-2021 艾星Aistra 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.icebem.akt.overlay 19 | 20 | import android.graphics.PixelFormat 21 | import android.os.Build 22 | import android.view.* 23 | import android.view.View.OnTouchListener 24 | import androidx.core.content.ContextCompat 25 | import com.icebem.akt.R 26 | import kotlin.math.abs 27 | 28 | class OverlayView(val view: View) { 29 | private var x = 0 30 | private var y = 0 31 | private var handled = false 32 | private var showing = false 33 | private val touchSlop = ViewConfiguration.get(view.context).scaledTouchSlop 34 | private val manager: WindowManager = ContextCompat.getSystemService(view.context, WindowManager::class.java)!! 35 | 36 | @Suppress("DEPRECATION", "PrivateResource") 37 | private val params: WindowManager.LayoutParams = WindowManager.LayoutParams().apply { 38 | height = WindowManager.LayoutParams.WRAP_CONTENT 39 | width = height 40 | flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM 41 | format = PixelFormat.RGBA_8888 42 | type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_PHONE 43 | windowAnimations = R.style.MaterialAlertDialog_Material3_Animation 44 | } 45 | 46 | init { 47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) view.isForceDarkAllowed = false 48 | } 49 | 50 | fun show(): OverlayView { 51 | if (!showing) { 52 | manager.addView(view, params) 53 | showing = true 54 | } 55 | return this 56 | } 57 | 58 | fun showAfterRemove(showing: OverlayView): OverlayView { 59 | if (showing !== this) showing.remove() 60 | return show() 61 | } 62 | 63 | fun remove() { 64 | if (showing) { 65 | manager.removeView(view) 66 | showing = false 67 | } 68 | } 69 | 70 | private fun update() { 71 | if (showing) manager.updateViewLayout(view, params) 72 | } 73 | 74 | fun resize(width: Int, height: Int) { 75 | params.width = width 76 | params.height = height 77 | update() 78 | } 79 | 80 | fun setGravity(gravity: Int) { 81 | params.gravity = gravity 82 | update() 83 | } 84 | 85 | fun setMobilizable(mobilizable: Boolean) { 86 | view.setOnTouchListener(if (mobilizable) OnTouchListener { view: View, event: MotionEvent -> 87 | when (event.action) { 88 | MotionEvent.ACTION_DOWN -> { 89 | handled = false 90 | x = event.rawX.toInt() 91 | y = event.rawY.toInt() 92 | view.postDelayed({ handled = handled || view.performLongClick() }, ViewConfiguration.getLongPressTimeout().toLong()) 93 | } 94 | MotionEvent.ACTION_UP -> if (!handled) handled = view.performClick() 95 | MotionEvent.ACTION_MOVE -> { 96 | if (!handled) { 97 | if (abs(event.rawX.toInt() - x) < touchSlop && abs(event.rawY.toInt() - y) < touchSlop) return@OnTouchListener true 98 | handled = true 99 | } 100 | if (params.gravity == params.gravity or Gravity.END && params.gravity != params.gravity or Gravity.START) params.x -= event.rawX.toInt() - x else params.x += event.rawX.toInt() - x 101 | if (params.gravity == params.gravity or Gravity.BOTTOM && params.gravity != params.gravity or Gravity.TOP) params.y -= event.rawY.toInt() - y else params.y += event.rawY.toInt() - y 102 | x = event.rawX.toInt() 103 | y = event.rawY.toInt() 104 | update() 105 | } 106 | } 107 | true 108 | } else null) 109 | } 110 | 111 | fun setRelativePosition(x: Int, y: Int) { 112 | params.x = x 113 | params.y = y 114 | update() 115 | } 116 | 117 | val relativeX: Int get() = params.x 118 | val relativeY: Int get() = params.y 119 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/service/GestureService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ArkTap. 3 | * Copyright (C) 2019-2021 艾星Aistra 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.icebem.akt.service 19 | 20 | import android.accessibilityservice.AccessibilityService 21 | import android.content.Intent 22 | import android.util.Log 23 | import android.view.KeyEvent 24 | import android.view.accessibility.AccessibilityEvent 25 | import androidx.lifecycle.MutableLiveData 26 | import androidx.lifecycle.Observer 27 | import com.icebem.akt.BuildConfig 28 | import com.icebem.akt.R 29 | import com.icebem.akt.overlay.OverlayToast 30 | import com.icebem.akt.util.ArkData 31 | import com.icebem.akt.util.ArkMaid 32 | import com.icebem.akt.util.ArkPref 33 | import com.icebem.akt.util.Random 34 | import kotlinx.coroutines.* 35 | import java.lang.ref.WeakReference 36 | 37 | class GestureService : AccessibilityService(), Observer { 38 | companion object { 39 | private const val WAIT_TIME = 3500L 40 | private const val MINUTE_TIME = 60000L 41 | private var instance: WeakReference? = null 42 | 43 | val isGestureRunning: Boolean get() = instance?.get()?.running == true 44 | val action = MutableLiveData() 45 | fun toggle() = action.postValue(true) 46 | } 47 | 48 | private var running = false 49 | private var gesture: Job? = null 50 | private var timer: Job? = null 51 | 52 | override fun onServiceConnected() { 53 | super.onServiceConnected() 54 | if (!ArkPref.isActivated) ArkPref.setActivatedId() 55 | if (ArkMaid.requireOverlayPermission || ArkPref.unsupportedResolution || ArkMaid.requireRootPermission) { 56 | ArkMaid.disableSelf(this, ::stopAction) 57 | when { 58 | ArkMaid.requireOverlayPermission -> ArkMaid.startManageOverlay(this) 59 | ArkPref.unsupportedResolution -> OverlayToast.show(R.string.state_resolution_unsupported, OverlayToast.LENGTH_LONG) 60 | ArkMaid.requireRootPermission -> OverlayToast.show(R.string.root_mode_msg, OverlayToast.LENGTH_LONG) 61 | } 62 | return 63 | } 64 | action.observeForever(this) 65 | if (ArkPref.noBackground) toggle() 66 | } 67 | 68 | override fun onChanged(value: Boolean) { 69 | if (!value) return 70 | instance = WeakReference(this) 71 | if (running) pauseAction() else startAction() 72 | action.postValue(false) 73 | } 74 | 75 | private fun startAction() { 76 | running = true 77 | gesture?.cancel() 78 | timer?.cancel() 79 | startService(Intent(this, OverlayService::class.java)) 80 | CoroutineScope(Dispatchers.Default).launch { 81 | gesture = launch { 82 | delay(WAIT_TIME) 83 | if (ArkData.hasGestureData) performCustomizedGestures() 84 | else performGestures() 85 | } 86 | var time = ArkPref.timerTime 87 | if (time > 0) { 88 | timer = launch { 89 | while (time > 0) { 90 | showTimeLeft(time--) 91 | delay(MINUTE_TIME) 92 | } 93 | performGlobalAction(GLOBAL_ACTION_HOME) 94 | pauseAction() 95 | } 96 | } else showGestureTip(R.string.info_gesture_connected) 97 | } 98 | } 99 | 100 | private fun pauseAction() { 101 | if (ArkPref.noBackground) ArkMaid.disableSelf(this, ::stopAction) else stopAction() 102 | } 103 | 104 | private fun stopAction() { 105 | running = false 106 | gesture?.cancel() 107 | timer?.cancel() 108 | runCatching { OverlayToast.show(R.string.info_gesture_disconnected, OverlayToast.LENGTH_SHORT) } 109 | } 110 | 111 | private suspend fun performGestures() { 112 | var process = 0 113 | while (true) { 114 | when (process++) { 115 | 0 -> ArkMaid.performClick(this, ArkPref.blueX, ArkPref.blueY) 116 | 1 -> if (ArkPref.greenPoint) ArkMaid.performClick(this, ArkPref.greenX, ArkPref.greenY) 117 | 2 -> ArkMaid.performClick(this, ArkPref.redX, ArkPref.redY) 118 | 3 -> if (ArkPref.greenPoint) ArkMaid.performClick(this, ArkPref.greenX, ArkPref.greenY) 119 | 4 -> if (ArkPref.greenPoint) ArkMaid.performClick(this, ArkPref.greenX, ArkPref.greenY) 120 | } 121 | if (process > 4) process = 0 122 | delay(Random.randomTime(ArkPref.updateTime)) 123 | } 124 | } 125 | 126 | private suspend fun performCustomizedGestures() { 127 | val array = ArkData.getGestureData() 128 | var process = 0 129 | while (true) { 130 | val obj = array.getJSONObject(process) 131 | when (obj.optString(ArkData.KEY_NAME)) { 132 | ArkData.KEY_TAP -> 133 | ArkMaid.performClick(this, obj.optInt(ArkData.KEY_X), obj.optInt(ArkData.KEY_Y)) 134 | } 135 | if (++process == array.length()) process = 0 136 | delay(Random.randomTime(if (obj.optInt(ArkData.KEY_DELAY) > 0) obj.optInt(ArkData.KEY_DELAY) else ArkPref.updateTime)) 137 | } 138 | } 139 | 140 | private suspend fun showGestureTip(resId: Int) = withContext(Dispatchers.Main) { OverlayToast.show(resId, OverlayToast.LENGTH_SHORT) } 141 | 142 | private suspend fun showTimeLeft(time: Int) = withContext(Dispatchers.Main) { OverlayToast.show(getString(R.string.info_gesture_running, time), OverlayToast.LENGTH_SHORT) } 143 | 144 | override fun onAccessibilityEvent(event: AccessibilityEvent) { 145 | if (BuildConfig.DEBUG) Log.d(javaClass.simpleName, "onAccessibilityEvent: $event") 146 | } 147 | 148 | override fun onInterrupt() { 149 | if (BuildConfig.DEBUG) Log.d(javaClass.simpleName, "onInterrupt") 150 | } 151 | 152 | override fun onUnbind(intent: Intent): Boolean { 153 | action.removeObserver(this) 154 | stopAction() 155 | return super.onUnbind(intent) 156 | } 157 | 158 | override fun onKeyEvent(event: KeyEvent): Boolean { 159 | if (running && event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && ArkPref.volumeControl) { 160 | pauseAction() 161 | return true 162 | } 163 | return false 164 | } 165 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/service/QSTileService.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.service 2 | 3 | import android.content.Intent 4 | import android.graphics.drawable.Icon 5 | import android.os.Build 6 | import android.service.quicksettings.Tile 7 | import android.service.quicksettings.TileService 8 | import androidx.annotation.RequiresApi 9 | import androidx.core.content.ContextCompat 10 | import com.icebem.akt.R 11 | import com.icebem.akt.util.ArkMaid 12 | 13 | @RequiresApi(Build.VERSION_CODES.N) 14 | class QSTileService : TileService() { 15 | override fun onStartListening() { 16 | super.onStartListening() 17 | qsTile.icon = Icon.createWithResource(this, if (ArkMaid.requireOverlayPermission) R.drawable.ic_error else R.drawable.ic_akt) 18 | qsTile.label = getString(if (ArkMaid.requireOverlayPermission) R.string.state_permission_request else R.string.overlay_label) 19 | qsTile.state = if (ArkMaid.isOverlayServiceRunning) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE 20 | qsTile.updateTile() 21 | } 22 | 23 | override fun onClick() { 24 | super.onClick() 25 | if (ArkMaid.requireOverlayPermission) { 26 | ArkMaid.startManageOverlay(this) 27 | } else { 28 | val intent = Intent(this, OverlayService::class.java) 29 | if (ArkMaid.isOverlayServiceRunning) { 30 | stopService(intent) 31 | qsTile.state = Tile.STATE_INACTIVE 32 | } else { 33 | ContextCompat.startForegroundService(this, intent) 34 | qsTile.state = Tile.STATE_ACTIVE 35 | } 36 | qsTile.updateTile() 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/ui/about/AboutFragment.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.ui.about 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.View.OnClickListener 9 | import android.view.ViewGroup 10 | import androidx.fragment.app.Fragment 11 | import androidx.lifecycle.lifecycleScope 12 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 13 | import com.google.android.material.snackbar.Snackbar 14 | import com.icebem.akt.BuildConfig 15 | import com.icebem.akt.R 16 | import com.icebem.akt.databinding.FragmentAboutBinding 17 | import com.icebem.akt.model.ContributorInfo 18 | import com.icebem.akt.util.ArkData 19 | import com.icebem.akt.util.ArkMaid 20 | import com.icebem.akt.util.ArkPref 21 | import org.json.JSONArray 22 | 23 | class AboutFragment : Fragment(), OnClickListener { 24 | private var _binding: FragmentAboutBinding? = null 25 | private val binding get() = _binding!! 26 | 27 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { 28 | _binding = FragmentAboutBinding.inflate(layoutInflater) 29 | ArkData.updateResult.observe(viewLifecycleOwner, ::handleUpdateResult) 30 | binding.txtVersionStateDesc.text = BuildConfig.VERSION_NAME 31 | binding.txtVersionTypeDesc.setText(if (ArkPref.isPro) R.string.version_type_pro else R.string.version_type_lite) 32 | binding.containerVersionState.setOnClickListener(this) 33 | binding.containerVersionState.setOnLongClickListener { resetDataDialog() } 34 | binding.containerVersionType.setOnClickListener(this) 35 | binding.containerVersionType.setOnLongClickListener { ArkMaid.reinstallSelf(requireContext()) } 36 | binding.containerComment.setOnClickListener(this) 37 | binding.containerProject.setOnClickListener(this) 38 | binding.containerDiscuss.setOnClickListener(this) 39 | binding.containerSupport.setOnClickListener(this) 40 | binding.actionShare.setOnClickListener(this) 41 | binding.actionDonate.setOnClickListener(this) 42 | binding.contributorsText.text = buildString { 43 | ContributorInfo.array.forEach { 44 | if (isNotEmpty()) appendLine() 45 | append(it.toLocalizedString(resources)) 46 | } 47 | } 48 | return binding.root 49 | } 50 | 51 | override fun onClick(view: View) { 52 | when (view.id) { 53 | R.id.container_version_state -> { 54 | view.isClickable = false 55 | view.isLongClickable = false 56 | ArkMaid.startUpdate(lifecycleScope, view) 57 | } 58 | R.id.container_version_type -> { 59 | view.tag = (view.tag as? Int)?.plus(1) ?: 1 60 | if (view.tag == 15) { 61 | view.tag = 0 62 | ArkPref.isPro = !ArkPref.isPro 63 | binding.txtVersionTypeDesc.setText(if (ArkPref.isPro) R.string.version_type_pro else R.string.version_type_lite) 64 | Snackbar.make(view, R.string.version_type_changed, Snackbar.LENGTH_INDEFINITE).setAction(R.string.action_reinstall) { ArkMaid.reinstallSelf(requireContext()) }.show() 65 | if (ArkPref.isPro) ArkMaid.showRootDialog(requireActivity()) 66 | } 67 | } 68 | R.id.container_comment -> ArkMaid.startUrl(requireActivity(), ArkMaid.URL_COOLAPK) 69 | R.id.container_project -> ArkMaid.startUrl(requireActivity(), ArkMaid.URL_PROJECT) 70 | R.id.container_discuss -> runCatching { 71 | ArkMaid.startUrl(requireActivity(), ArkMaid.URL_QQ_API) 72 | } 73 | R.id.container_support -> ArkMaid.startUrl(requireActivity(), ArkMaid.URL_WHY_FREE_SOFTWARE) 74 | R.id.action_share -> startActivity(Intent(Intent.ACTION_SEND).putExtra(Intent.EXTRA_TEXT, ArkMaid.URL_COOLAPK).setType("text/plain")) 75 | R.id.action_donate -> onDonate() 76 | } 77 | } 78 | 79 | private fun resetDataDialog(): Boolean { 80 | MaterialAlertDialogBuilder(requireActivity()).run { 81 | setTitle(R.string.action_reset) 82 | setMessage(R.string.msg_data_reset) 83 | setPositiveButton(R.string.action_reset) { _, _ -> 84 | var id = R.string.data_reset_done 85 | runCatching { 86 | ArkData.resetData() 87 | ArkPref.setCheckLastTime(false) 88 | }.onFailure { 89 | Log.e(javaClass.simpleName, it.toString()) 90 | id = R.string.error_occurred 91 | } 92 | Snackbar.make(binding.root, id, Snackbar.LENGTH_LONG).show() 93 | } 94 | setNegativeButton(android.R.string.cancel, null) 95 | show() 96 | } 97 | return true 98 | } 99 | 100 | private fun onDonate() { 101 | MaterialAlertDialogBuilder(requireActivity()).run { 102 | setTitle(R.string.action_donate) 103 | setSingleChoiceItems(resources.getStringArray(R.array.donate_payment_entries), 0) { dialog, which -> 104 | dialog.dismiss() 105 | when (which) { 106 | 0 -> runCatching { 107 | startActivity(Intent.parseUri(ArkMaid.URL_ALIPAY_API, Intent.URI_INTENT_SCHEME)) 108 | }.onFailure { 109 | showQRDialog(true) 110 | } 111 | 1 -> showQRDialog(false) 112 | 2 -> ArkMaid.startUrl(requireActivity(), ArkMaid.URL_PAYPAL) 113 | } 114 | Snackbar.make(binding.root, R.string.info_donate_thanks, Snackbar.LENGTH_INDEFINITE).show() 115 | } 116 | setNegativeButton(R.string.not_now, null) 117 | show() 118 | } 119 | } 120 | 121 | private fun showQRDialog(isAlipay: Boolean) { 122 | MaterialAlertDialogBuilder(requireActivity()).run { 123 | setTitle(R.string.action_donate) 124 | setView(if (isAlipay) R.layout.qr_alipay else R.layout.qr_wechat) 125 | setPositiveButton(R.string.not_now, null) 126 | show() 127 | } 128 | } 129 | 130 | private fun handleUpdateResult(result: JSONArray?) = ArkMaid.showUpdateResult(requireActivity(), binding.root, result) { 131 | binding.containerVersionState.isClickable = true 132 | binding.containerVersionState.isLongClickable = true 133 | } 134 | 135 | override fun onDestroyView() { 136 | super.onDestroyView() 137 | _binding = null 138 | } 139 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/ui/home/HomeFragment.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.ui.home 2 | 3 | import android.graphics.drawable.Animatable 4 | import android.graphics.drawable.Drawable 5 | import android.os.Bundle 6 | import android.view.LayoutInflater 7 | import android.view.Menu 8 | import android.view.MenuInflater 9 | import android.view.MenuItem 10 | import android.view.View 11 | import android.view.View.OnClickListener 12 | import android.view.ViewGroup 13 | import android.widget.FrameLayout 14 | import androidx.appcompat.app.AppCompatDelegate 15 | import androidx.core.view.MenuHost 16 | import androidx.core.view.MenuProvider 17 | import androidx.fragment.app.Fragment 18 | import androidx.lifecycle.Lifecycle 19 | import androidx.lifecycle.lifecycleScope 20 | import androidx.navigation.fragment.findNavController 21 | import androidx.vectordrawable.graphics.drawable.Animatable2Compat 22 | import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat 23 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 24 | import com.google.android.material.snackbar.Snackbar 25 | import com.icebem.akt.R 26 | import com.icebem.akt.databinding.DialogInputBinding 27 | import com.icebem.akt.databinding.FragmentHomeBinding 28 | import com.icebem.akt.util.ArkData 29 | import com.icebem.akt.util.ArkMaid 30 | import com.icebem.akt.util.ArkPref 31 | import com.icebem.akt.util.Resolution 32 | import org.json.JSONArray 33 | import java.text.SimpleDateFormat 34 | 35 | class HomeFragment : Fragment(), MenuProvider, OnClickListener { 36 | private var _binding: FragmentHomeBinding? = null 37 | private val binding get() = _binding!! 38 | private val callback by lazy { AnimCallback() } 39 | 40 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { 41 | val menuHost = requireActivity() as MenuHost 42 | menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) 43 | _binding = FragmentHomeBinding.inflate(layoutInflater) 44 | ArkData.updateResult.observe(viewLifecycleOwner, ::handleUpdateResult) 45 | binding.txtData.text = SimpleDateFormat.getDateTimeInstance().format(ArkPref.checkLastTime) 46 | binding.navRecruit.setOnClickListener(this) 47 | binding.navSettings.setOnClickListener(this) 48 | binding.navAbout.setOnClickListener(this) 49 | binding.actionWiki.setOnClickListener(this) 50 | binding.actionPenguin.setOnClickListener(this) 51 | return binding.root 52 | } 53 | 54 | override fun onClick(view: View) { 55 | when (view.id) { 56 | R.id.txt_tips -> { 57 | ArkPref.isPro = true 58 | Snackbar.make(view, R.string.version_type_changed, Snackbar.LENGTH_INDEFINITE).setAction(R.string.action_reinstall) { ArkMaid.reinstallSelf(requireContext()) }.show() 59 | } 60 | R.id.img_state -> { 61 | view.tag = (view.tag as? Int)?.plus(1) ?: 1 62 | if (view.tag in 3 until 15) { 63 | if (view.tag == 3) { 64 | binding.imgState.setImageResource(R.drawable.ic_state_error_anim) 65 | binding.txtState.setText(R.string.error_occurred) 66 | binding.txtTips.setText(R.string.error_slogan) 67 | } 68 | (binding.imgState.drawable as Animatable).start() 69 | } else if (view.tag == 15) { 70 | view.tag = 0 71 | callback.onAnimationEnd(binding.imgState.drawable) 72 | } 73 | } 74 | R.id.action_wiki -> ArkMaid.startUrl(requireActivity(), ArkMaid.URL_PRTS_WIKI) 75 | R.id.action_penguin -> ArkMaid.startUrl(requireActivity(), ArkMaid.URL_PENGUIN_STATS) 76 | else -> findNavController().navigate(view.id) 77 | } 78 | } 79 | 80 | override fun onStart() { 81 | super.onStart() 82 | if (ArkPref.autoUpdate) ArkMaid.startUpdate(lifecycleScope, binding.root) else onStateEnd() 83 | if (ArkPref.isPro) binding.imgState.setOnLongClickListener { 84 | val input = DialogInputBinding.inflate(layoutInflater, FrameLayout(requireActivity()), true) 85 | input.inputLayout.setHint(R.string.customize_points) 86 | input.editText.setText(ArkData.getGestureData().toString()) 87 | MaterialAlertDialogBuilder(requireActivity()).run { 88 | setView(input.root.parent as View) 89 | setPositiveButton(android.R.string.ok) { _, _ -> if (!ArkData.setGestureData(input.editText.text.toString())) Snackbar.make(it, R.string.wrong_format, Snackbar.LENGTH_LONG).show() } 90 | setNeutralButton(R.string.action_reset) { _, _ -> ArkData.resetGestureData() } 91 | setNegativeButton(android.R.string.cancel, null) 92 | show() 93 | } 94 | true 95 | } 96 | } 97 | 98 | private fun handleUpdateResult(result: JSONArray?) = ArkMaid.showUpdateResult(requireActivity(), binding.root, result) { 99 | binding.txtData.text = SimpleDateFormat.getDateTimeInstance().format(ArkPref.checkLastTime) 100 | onStateEnd() 101 | } 102 | 103 | private fun onStateEnd() { 104 | if (ArkPref.isPro && ArkPref.unsupportedResolution) { 105 | binding.imgState.setImageResource(R.drawable.ic_state_running) 106 | binding.txtState.setText(R.string.state_resolution_unsupported) 107 | val res = Resolution.physicalResolution 108 | MaterialAlertDialogBuilder(requireActivity()).run { 109 | setTitle(R.string.state_resolution_unsupported) 110 | setMessage(getString(R.string.msg_resolution_unsupported, res[0], res[1])) 111 | setPositiveButton(R.string.not_now, null) 112 | setNeutralButton(R.string.action_update) { _, _ -> ArkMaid.startUpdate(lifecycleScope, binding.root) } 113 | show() 114 | } 115 | } else { 116 | binding.imgState.setImageResource(R.drawable.ic_state_running_anim) 117 | binding.txtState.setText(R.string.state_loading) 118 | AnimatedVectorDrawableCompat.registerAnimationCallback(binding.imgState.drawable, callback) 119 | (binding.imgState.drawable as Animatable).start() 120 | } 121 | } 122 | 123 | private inner class AnimCallback : Animatable2Compat.AnimationCallback() { 124 | override fun onAnimationEnd(drawable: Drawable) { 125 | binding.imgState.setImageResource(R.drawable.ic_state_ready_anim) 126 | binding.txtState.setText(R.string.state_ready) 127 | if (ArkPref.isPro && !ArkPref.isActivated) { 128 | binding.txtTips.setText(R.string.tip_not_found) 129 | binding.txtTips.setOnClickListener(this@HomeFragment) 130 | } else binding.txtTips.text = ArkPref.nextSlogan 131 | (binding.imgState.drawable as Animatable).start() 132 | if (!binding.imgState.hasOnClickListeners()) binding.imgState.setOnClickListener(this@HomeFragment) 133 | } 134 | } 135 | 136 | override fun onMenuItemSelected(item: MenuItem): Boolean { 137 | when (item.itemId) { 138 | R.id.action_timer -> MaterialAlertDialogBuilder(requireActivity()).run { 139 | setTitle(R.string.action_timer) 140 | setSingleChoiceItems(ArkPref.timerStrings, ArkPref.timerPosition) { dialog, which -> 141 | dialog.dismiss() 142 | ArkPref.timerTime = which 143 | Snackbar.make(binding.root, getString(R.string.info_timer_set, if (ArkPref.timerTime == 0) getString(R.string.info_timer_none) else getString(R.string.info_timer_min, ArkPref.timerTime)), Snackbar.LENGTH_LONG).show() 144 | } 145 | setNegativeButton(android.R.string.cancel, null) 146 | show() 147 | } 148 | R.id.action_night -> AppCompatDelegate.setDefaultNightMode(if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else AppCompatDelegate.MODE_NIGHT_YES) 149 | } 150 | return false 151 | } 152 | 153 | override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { 154 | inflater.inflate(R.menu.menu_home, menu) 155 | if (ArkPref.isPro) menu.findItem(R.id.action_timer).isVisible = true 156 | } 157 | 158 | override fun onDestroyView() { 159 | AnimatedVectorDrawableCompat.clearAnimationCallbacks(binding.imgState.drawable) 160 | super.onDestroyView() 161 | _binding = null 162 | } 163 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/ui/main/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.ui.main 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import android.view.View.OnLongClickListener 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.navigation.NavController 8 | import androidx.navigation.NavDestination 9 | import androidx.navigation.findNavController 10 | import androidx.navigation.ui.AppBarConfiguration 11 | import androidx.navigation.ui.navigateUp 12 | import androidx.navigation.ui.setupActionBarWithNavController 13 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 14 | import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton 15 | import com.icebem.akt.R 16 | import com.icebem.akt.databinding.ActivityMainBinding 17 | import com.icebem.akt.service.GestureService 18 | import com.icebem.akt.util.ArkMaid 19 | import com.icebem.akt.util.ArkPref 20 | 21 | class MainActivity : AppCompatActivity(), OnLongClickListener, NavController.OnDestinationChangedListener { 22 | private lateinit var fab: ExtendedFloatingActionButton 23 | private lateinit var navController: NavController 24 | private lateinit var appBarConfiguration: AppBarConfiguration 25 | 26 | override fun onCreate(savedInstanceState: Bundle?) { 27 | super.onCreate(savedInstanceState) 28 | val binding = ActivityMainBinding.inflate(layoutInflater) 29 | setContentView(binding.root) 30 | setSupportActionBar(binding.toolbar) 31 | fab = binding.fab 32 | fab.setOnClickListener { ArkMaid.requireOverlayService(this) } 33 | fab.setOnLongClickListener(this) 34 | navController = findNavController(R.id.nav_host_fragment) 35 | navController.addOnDestinationChangedListener(this) 36 | appBarConfiguration = AppBarConfiguration.Builder(R.id.nav_home).build() 37 | setupActionBarWithNavController(navController, appBarConfiguration) 38 | } 39 | 40 | override fun onSupportNavigateUp(): Boolean = navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() 41 | 42 | 43 | override fun onDestinationChanged(controller: NavController, destination: NavDestination, arguments: Bundle?) { 44 | if (destination.id != R.id.nav_home) fab.hide() else fab.show() 45 | } 46 | 47 | override fun onLongClick(v: View?): Boolean { 48 | if (!ArkPref.isPro) return false 49 | when { 50 | ArkMaid.isGestureServiceRunning -> GestureService.toggle() 51 | ArkMaid.isGestureServiceEnabled -> MaterialAlertDialogBuilder(this).run { 52 | setTitle(R.string.error_occurred) 53 | setMessage(R.string.error_accessibility_killed) 54 | setPositiveButton(R.string.action_reinstall) { _, _ -> ArkMaid.reinstallSelf(this@MainActivity) } 55 | setNegativeButton(android.R.string.cancel, null) 56 | show() 57 | } 58 | else -> ArkMaid.startManageAccessibility(this) 59 | } 60 | return true 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/ui/recruit/RecruitFragment.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.ui.recruit 2 | 3 | import android.os.Bundle 4 | import android.view.* 5 | import androidx.core.view.MenuHost 6 | import androidx.core.view.MenuProvider 7 | import androidx.fragment.app.Fragment 8 | import androidx.lifecycle.Lifecycle 9 | import androidx.lifecycle.lifecycleScope 10 | import com.icebem.akt.R 11 | import com.icebem.akt.databinding.FragmentRecruitBinding 12 | import com.icebem.akt.model.RecruitViewer 13 | import com.icebem.akt.util.ArkMaid 14 | import com.icebem.akt.util.ArkPref 15 | import kotlinx.coroutines.launch 16 | 17 | class RecruitFragment : Fragment(), MenuProvider { 18 | private var viewer: RecruitViewer? = null 19 | 20 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { 21 | val menuHost = requireActivity() as MenuHost 22 | menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) 23 | return FragmentRecruitBinding.inflate(layoutInflater).run { 24 | root.visibility = View.INVISIBLE 25 | lifecycleScope.launch { 26 | runCatching { 27 | viewer = RecruitViewer(requireContext(), this@run) 28 | root.visibility = View.VISIBLE 29 | }.onFailure { 30 | ArkMaid.showLogDialog(requireActivity(), it.toString()) 31 | } 32 | } 33 | root 34 | } 35 | } 36 | 37 | override fun onMenuItemSelected(item: MenuItem): Boolean { 38 | when (item.itemId) { 39 | R.id.action_overlay -> ArkMaid.requireOverlayService(requireActivity()) 40 | R.id.action_language -> viewer?.toggleServer() 41 | } 42 | return false 43 | } 44 | 45 | override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { 46 | inflater.inflate(R.menu.menu_tools, menu) 47 | if (ArkPref.multiPackage) menu.findItem(R.id.action_language).isVisible = true 48 | } 49 | 50 | override fun onDestroyView() { 51 | super.onDestroyView() 52 | viewer = null 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/ui/settings/SettingsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.ui.settings 2 | 3 | import android.os.Build 4 | import android.os.Bundle 5 | import androidx.preference.Preference 6 | import androidx.preference.PreferenceFragmentCompat 7 | import com.icebem.akt.R 8 | import com.icebem.akt.util.ArkPref 9 | 10 | class SettingsFragment : PreferenceFragmentCompat() { 11 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { 12 | setPreferencesFromResource(R.xml.root_preferences, rootKey) 13 | val preference = findPreference(when { 14 | !ArkPref.isPro -> "gesture_category" 15 | Build.VERSION.SDK_INT < Build.VERSION_CODES.N -> "no_background" 16 | else -> "" 17 | }) 18 | preference?.isVisible = false 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/util/ArkContributors.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.util 2 | 3 | import org.json.JSONArray 4 | import org.json.JSONException 5 | import java.io.IOException 6 | 7 | object ArkContributors { 8 | private const val CONTRIBUTORS_DATA_NAME = "contributors.json" 9 | private var CONTRIBUTORS_DATA : JSONArray? = null 10 | 11 | @Throws(IOException::class, JSONException::class) 12 | fun getContributorsData() : JSONArray { 13 | if (CONTRIBUTORS_DATA == null) { 14 | synchronized(ArkContributors) { 15 | if (CONTRIBUTORS_DATA == null) { 16 | CONTRIBUTORS_DATA = JSONArray(ArkIO.fromAssets(CONTRIBUTORS_DATA_NAME)) 17 | } 18 | } 19 | } 20 | return CONTRIBUTORS_DATA!! 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/util/ArkData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of ArkTap. 3 | * Copyright (C) 2019-2021 艾星Aistra 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.icebem.akt.util 19 | 20 | import androidx.lifecycle.MutableLiveData 21 | import com.icebem.akt.ArkApp.Companion.app 22 | import com.icebem.akt.BuildConfig 23 | import com.icebem.akt.R 24 | import org.json.JSONArray 25 | import org.json.JSONException 26 | import org.json.JSONObject 27 | import java.io.File 28 | import java.io.IOException 29 | 30 | /** 31 | * 数据更新相关 32 | */ 33 | object ArkData { 34 | const val INDEX_EN = 0 35 | const val INDEX_CN = 1 36 | const val INDEX_TW = 2 37 | const val INDEX_JP = 3 38 | const val INDEX_KR = 4 39 | const val FLAG_UNRELEASED = "*" 40 | const val KEY_NAME = "name" 41 | const val KEY_DELAY = "delay" 42 | const val KEY_TAP = "tap" 43 | const val KEY_X = "x" 44 | const val KEY_Y = "y" 45 | private const val KEY_COMPAT = "compat" 46 | private const val KEY_VERSION = "version" 47 | private const val TYPE_DATA = "data" 48 | private const val DATA_ENTRY = "entry.json" 49 | private const val DATA_MATERIAL = "material.json" 50 | private const val DATA_RECRUIT = "recruit.json" 51 | private const val DATA_RESOLUTION = "resolution.json" 52 | private const val DATA_SLOGAN = "slogan.json" 53 | private const val DATA_GESTURE = "gesture.json" 54 | private const val URL_WEB_DATA = "https://github.com/aistra0528/ArknightsTap/raw/master/app/src/main/assets/data/" 55 | val updateResult = MutableLiveData() 56 | 57 | suspend fun requireUpdate() { 58 | var id = R.string.version_update 59 | var log = String() 60 | var url = ArkMaid.URL_RELEASE_LATEST 61 | runCatching { 62 | val entry = requestOnlineEntry() 63 | if (latestApp(entry)) { 64 | id = if (updateData(entry)) R.string.data_updated else R.string.version_latest 65 | } else { 66 | val json = JSONObject(ArkIO.fromWeb(ArkMaid.URL_RELEASE_LATEST_API)) 67 | log = getChangelog(json) 68 | url = getDownloadUrl(json) 69 | } 70 | ArkPref.setCheckLastTime(true) 71 | }.onFailure { 72 | id = R.string.version_checking_failed 73 | log = it.toString() 74 | } 75 | updateResult.postValue(JSONArray().put(id).put(log).put(url)) 76 | } 77 | 78 | @Throws(IOException::class, JSONException::class) 79 | suspend fun updateData(onlineEntry: JSONArray): Boolean { 80 | val entry = getOfflineData(DATA_ENTRY) 81 | var updated = false 82 | for (i in 0 until onlineEntry.length()) { 83 | val data = onlineEntry.getJSONObject(i) 84 | if (data.getString(KEY_NAME) == DATA_ENTRY) { 85 | if (!compatible(data)) return updated 86 | if (updatable(data, entry)) updated = true 87 | } else if (compatible(data) && (updatable(data, entry))) { 88 | updateOfflineData(data.getString(KEY_NAME), onlineEntry) 89 | updated = true 90 | } 91 | } 92 | if (updated) updateOfflineData(DATA_ENTRY, onlineEntry) 93 | return updated 94 | } 95 | 96 | @Throws(IOException::class, JSONException::class) 97 | fun resetData() = ArkIO.clearDirectory(app.filesDir.path) 98 | 99 | @Throws(IOException::class) 100 | private suspend fun updateOfflineData(data: String, onlineEntry: JSONArray) { 101 | ArkIO.writeText(app.filesDir.path + File.separatorChar + data, when (data) { 102 | DATA_ENTRY -> onlineEntry.toString() 103 | else -> ArkIO.fromWeb(URL_WEB_DATA + data) 104 | }) 105 | } 106 | 107 | val hasGestureData get() = ArkIO.exists(app.filesDir.path + File.separatorChar + DATA_GESTURE) 108 | 109 | @Throws(IOException::class) 110 | fun resetGestureData() = ArkIO.delete(app.filesDir.path + File.separatorChar + DATA_GESTURE) 111 | 112 | fun setGestureData(string: String? = null): Boolean { 113 | string ?: return false 114 | runCatching { 115 | val array = JSONArray(string) 116 | if (array.length() == 0) return false 117 | for (i in 0 until array.length()) { 118 | val obj = array.getJSONObject(i) 119 | if (obj.optString(KEY_NAME) != KEY_TAP || obj.optInt(KEY_X) <= 0 || obj.optInt(KEY_Y) <= 0) 120 | return false 121 | } 122 | ArkIO.writeText(app.filesDir.path + File.separatorChar + DATA_GESTURE, string) 123 | return true 124 | } 125 | return false 126 | } 127 | 128 | @Throws(IOException::class, JSONException::class) 129 | private fun getOfflineData(data: String): JSONArray { 130 | val path = app.filesDir.path + File.separatorChar + data 131 | return JSONArray(if (ArkIO.exists(path)) ArkIO.fromFile(path) else getAssetsData(data)) 132 | } 133 | 134 | private fun getAssetsData(data: String) = ArkIO.fromAssets(TYPE_DATA + File.separatorChar + data) 135 | 136 | @Throws(IOException::class, JSONException::class) 137 | fun getMaterialData(): JSONArray = getOfflineData(DATA_MATERIAL) 138 | 139 | @Throws(IOException::class, JSONException::class) 140 | fun getRecruitData(): JSONArray = getOfflineData(DATA_RECRUIT) 141 | 142 | @Throws(IOException::class, JSONException::class) 143 | fun getResolutionData(): JSONArray = getOfflineData(DATA_RESOLUTION) 144 | 145 | @Throws(IOException::class, JSONException::class) 146 | fun getSloganData(): JSONArray = getOfflineData(DATA_SLOGAN) 147 | 148 | @Throws(IOException::class, JSONException::class) 149 | fun getGestureData(): JSONArray = getOfflineData(DATA_GESTURE) 150 | 151 | @Throws(IOException::class, JSONException::class) 152 | private suspend fun requestOnlineEntry(): JSONArray = JSONArray(ArkIO.fromWeb(URL_WEB_DATA + DATA_ENTRY)) 153 | 154 | @Throws(JSONException::class) 155 | private fun updatable(data: JSONObject, entry: JSONArray): Boolean { 156 | for (i in 0 until entry.length()) if (entry.getJSONObject(i).getString(KEY_NAME) == data.getString(KEY_NAME)) return data.getInt(KEY_VERSION) > entry.getJSONObject(i).getInt(KEY_VERSION) 157 | return false 158 | } 159 | 160 | @Throws(JSONException::class) 161 | private fun compatible(data: JSONObject): Boolean = BuildConfig.VERSION_CODE >= data.getInt(KEY_COMPAT) 162 | 163 | @Throws(JSONException::class) 164 | private fun latestApp(onlineEntry: JSONArray): Boolean = BuildConfig.VERSION_CODE >= onlineEntry.getJSONObject(0).getInt(KEY_VERSION) 165 | 166 | @Throws(JSONException::class) 167 | private fun getChangelog(json: JSONObject): String = buildString { 168 | appendLine(json.getString("name")) 169 | append(json.getString("body")) 170 | } 171 | 172 | @Throws(JSONException::class) 173 | private fun getDownloadUrl(json: JSONObject): String = json.getJSONArray("assets").getJSONObject(0).getString("browser_download_url") 174 | } 175 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/util/ArkIO.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.util 2 | 3 | import android.os.Build 4 | import com.icebem.akt.ArkApp.Companion.app 5 | import kotlinx.coroutines.Dispatchers 6 | import kotlinx.coroutines.withContext 7 | import java.io.* 8 | import java.net.HttpURLConnection 9 | import java.net.URL 10 | import java.nio.file.Files 11 | import java.nio.file.Paths 12 | import java.nio.file.StandardCopyOption 13 | import kotlin.io.path.* 14 | 15 | object ArkIO { 16 | @Throws(IOException::class) 17 | private fun stream2String(stream: InputStream): String = stream.bufferedReader().use { it.readText() } 18 | 19 | @Throws(IOException::class) 20 | fun fromAssets(path: String): String = stream2String(app.assets.open(path)) 21 | 22 | /** 23 | * This method is not recommended on huge files. It has an internal limitation of 2 GB file size. 24 | */ 25 | @Throws(IOException::class) 26 | fun fromFile(path: String): String = File(path).readText() 27 | 28 | @Throws(IOException::class) 29 | suspend fun fromWeb(url: String): String = withContext(Dispatchers.IO) { 30 | (URL(url).openConnection() as HttpURLConnection).run { 31 | if (url.startsWith("https://gitee.com")) addRequestProperty("User-Agent", "Mozilla/5.0") 32 | stream2String(inputStream) 33 | } 34 | } 35 | 36 | @Throws(IOException::class) 37 | fun exists(path: String): Boolean = when { 38 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> Files.exists(Paths.get(path)) 39 | else -> File(path).exists() 40 | } 41 | 42 | @Throws(IOException::class) 43 | private fun createDirectories(dir: String): Boolean = when { 44 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> Files.createDirectories(Paths.get(dir)).exists() 45 | else -> File(dir).mkdirs() 46 | } 47 | 48 | @Throws(IOException::class) 49 | fun clearDirectory(path: String) { 50 | when { 51 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> Files.list(Paths.get(path)).forEach { 52 | if (it.isDirectory()) clearDirectory(it.pathString) 53 | it.deleteExisting() 54 | } 55 | else -> File(path).listFiles()?.forEach { 56 | if (it.isDirectory) clearDirectory(it.path) 57 | it.delete() 58 | } 59 | } 60 | } 61 | 62 | @Throws(IOException::class) 63 | fun delete(path: String): Boolean = when { 64 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> Files.deleteIfExists(Paths.get(path)) 65 | else -> File(path).delete() 66 | } 67 | 68 | @Throws(IOException::class) 69 | fun copy(source: String, target: String): File { 70 | val file = File(target) 71 | file.parent?.let { createDirectories(it) } 72 | when { 73 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> Files.copy(Paths.get(source), Paths.get(target), StandardCopyOption.REPLACE_EXISTING) 74 | else -> FileInputStream(source).channel.use { 75 | FileOutputStream(target).channel.use { out -> 76 | out.transferFrom(it, 0, it.size()) 77 | } 78 | } 79 | } 80 | return file 81 | } 82 | 83 | @Throws(IOException::class) 84 | fun writeText(path: String, text: String) { 85 | val file = File(path) 86 | file.parent?.let { createDirectories(it) } 87 | file.writeText(text) 88 | } 89 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/util/Random.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.util 2 | 3 | object Random { 4 | const val DELTA_POINT = 5 5 | private const val DELTA_TIME = 150 6 | 7 | private fun random(i: Int, delta: Int): Int = if (i > delta) i + (Math.random() * delta * 2).toInt() - delta else i 8 | 9 | fun randomIndex(length: Int): Int = (Math.random() * length).toInt() 10 | 11 | fun randomPoint(point: Int): Int = random(point, DELTA_POINT) 12 | 13 | fun randomTime(time: Int): Long = random(time, DELTA_TIME).toLong() 14 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/icebem/akt/util/Resolution.kt: -------------------------------------------------------------------------------- 1 | package com.icebem.akt.util 2 | 3 | import android.os.Build 4 | import android.util.DisplayMetrics 5 | import android.view.WindowManager 6 | import androidx.core.content.ContextCompat 7 | import com.icebem.akt.ArkApp.Companion.app 8 | 9 | object Resolution { 10 | val physicalResolution: IntArray 11 | get() = ContextCompat.getSystemService(app, WindowManager::class.java)!!.run { 12 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) currentWindowMetrics.bounds.run { 13 | intArrayOf(width(), height()) 14 | } else DisplayMetrics().also { defaultDisplay.getRealMetrics(it) }.run { 15 | intArrayOf(widthPixels, heightPixels) 16 | } 17 | }.sortedArrayDescending() 18 | val physicalHeight: Int get() = physicalResolution[1] 19 | } -------------------------------------------------------------------------------- /app/src/main/res/animator/anim_core_alpha.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/animator/anim_core_scale_x.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/animator/anim_core_scale_y.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/animator/anim_default.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/animator/anim_error_scale.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/color/color_checkbox_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox_star_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox_star_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox_star_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox_star_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox_star_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_checkbox_star_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_floating.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_oval.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_overlay.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_star_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_star_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_star_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_star_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_star_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_star_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_unchecked.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_toast.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_akt.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_collapse.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_counter.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_exit.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_headhunt_toggle.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_language.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launch.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_monochrome.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_layers.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lightbulb.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_night.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_place.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_recruit.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_remove.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sort.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_error.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 15 | 16 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_error_anim.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_ready.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_ready_anim.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_running.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_running_anim.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 9 | 12 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_storage.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_timer.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_update.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_tag.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_input.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/overlay_counter.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 23 | 24 | 31 | 32 | 40 | 41 | 42 | 50 | 51 | 55 | 56 | 65 | 66 | 75 | 76 | 85 | 86 | -------------------------------------------------------------------------------- /app/src/main/res/layout/overlay_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | 30 | 31 | 39 | 40 | 41 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/overlay_recruit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | 31 | 32 | 41 | 42 | 50 | 51 | 52 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/qr_alipay.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/qr_wechat.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/tag_overlay.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_home.xml: -------------------------------------------------------------------------------- 1 | 5 | 11 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_tools.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/qr_alipay.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-hdpi/qr_alipay.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/qr_wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-xhdpi/qr_wechat.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30011.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30012.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30013.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30014.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30021.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30022.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30023.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30024.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30031.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30031.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30032.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30032.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30033.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30034.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30041.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30041.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30042.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30043.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30044.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30044.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30051.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30052.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30053.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30054.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30054.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30061.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30061.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30062.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30062.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30063.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30063.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30064.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30064.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30073.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30073.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30074.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30083.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30083.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30084.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30084.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30093.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30093.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30094.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30094.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30103.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_30104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_30104.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31013.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31014.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31023.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31024.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31033.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31034.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31043.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31044.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31044.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31053.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31054.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31054.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31063.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31063.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap/mtl_31064.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/app/src/main/res/mipmap/mtl_31064.png -------------------------------------------------------------------------------- /app/src/main/res/navigation/mobile_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 18 | 19 | 23 | 24 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/values-en/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ArkTap 3 | ARGS™ 4 | ARGS™ can tap the mission start button automatically.\n\nChoose a mission before start, and don\'t forget to allow Auto Deploy.\n\nUSING ARGS™ MAY LEAD TO ACCOUNT BANS, and we are NOT responsible for this. YOU are choosing to use ARGS™, and if you point the finger at us, we will laugh at you.\n\nThe permissions required by ARGS™ are ONLY used to tap the screen, and it do NOT collect any personal information.\n\nIf you have any questions, please feel free to contact us on GitHub. 5 | ARSS™ 6 | Settings 7 | App needs permissions 8 | Resolution not supported 9 | Service loading… 10 | Ready to connect 11 | - Display over other apps\nShow a floating window in game to help 12 | ARSS™ connected 13 | ARSS™ disconnected 14 | Fin 15 | Min 16 | Recruit Guide 17 | Reset 18 | No operators 19 | Possible operators 20 | Support Machine and 3:50 guarantees a 1★ operator 21 | 4★ or higher operators guarantees 22 | 5★ or higher operators guarantees! 23 | Advanced Senior and 9 hour, guarantees a 6★ operator! Congratulations! 24 | ARGS™ Running time 25 | %d min 26 | 27 | Set time for %s 28 | Night mode 29 | Please start ARGS™ 30 | ARGS™ start taping 31 | ARGS™ finished 32 | ARGS™ is running, %d min left 33 | Your device (%1$d×%2$d resolution) does not support ARGS™ yet, please contact us on GitHub. \nARSS™ is available without being affected. 34 | About 35 | Donate 36 | You can show your gratitude to the developer by making a donation. 37 | Thanks for your trust, Doctor 38 | Rate this app 39 | Rate the app on the store 40 | Join the conversation 41 | You can follow us on GitHub for updates 42 | Contributing to ArkTap 43 | Submit issues or pull requests on GitHub 44 | Current version 45 | Checking for updates… 46 | Check for updates failed 47 | This is the latest version 48 | New version available 49 | Version type 50 | Version type changed, please reinstall app 51 | Update 52 | Got it 53 | Allow 54 | No thanks 55 | Not now 56 | Error occurred 57 | Coming soon 58 | Auto check 59 | Check for updates according to the schedule 60 | You can check for updates by going to About 61 | Launch game 62 | Launch the game if necessary 63 | Game server 64 | Asc sorted 65 | Sort operators by ★ in ascending order 66 | Show unreleased 67 | Show unreleased operators in current server 68 | Quick nav 69 | Scroll to the result area after choosing 5 tags 70 | Special thanks 71 | Headhunt Counter 72 | Rolls: %1$d\nPossibility of 6★ in the next roll: %2$d%%\nLong press + to x10, - to clear 73 | Reset downloaded data? 74 | Reset successfully 75 | Latest data updated 76 | Material Guide 77 | Double speed 78 | Operate at 2x speed 79 | Data from Penguin Statistics, for reference only 80 | %s > Workshop 81 | %1$s | %2$.1f%% | %3$.1f Sanity 82 | Standard headhunt 83 | Limited headhunt 84 | Translucent sprite 85 | 减少内存占用 86 | 打开无障碍后开始,结束后关闭无障碍 87 | Root is required. 88 | Details 89 | Accessibility was killed, please reinstall app 90 | ARGS™ not found in Accessibility? Click here 91 | Reinstall 92 | Share 93 | Support 94 | Volume down to stop 95 | Customize points 96 | Wrong format 97 | 额外点击坐标 98 | 防止嗑药碎石和结算循环 99 | Penguin Statistics 100 | PRTS Wiki 101 | Alipay 102 | WeChat Pay 103 | PayPal 104 | Contributor 105 | Translator 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/values-in/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ArkTap 3 | ARGS™ 4 | ARGS™ dapat menekan tombol Mulai Misi secara otomatis.\n\nPilih Misi sebelum memulai, dan jangan lupa mengaktifkan Auto Deploy.\n\nMenggunakan ARGS™ dapat menyebabkan akun anda diBAN, dan kami TIDAK bertanggung jawab untuk ini. Anda memilih untuk menggunakan ARGS™, dan jika anda menyalahkan kami, kami hanya akan menertawakan anda\n\nIzin Yang Diperlukan Oleh ARGS™ Hanya Digunakan Untuk Menekan layar, dan ini tidak merekam informasi pribadi anda\n\nJika anda punya pertanyaan, silahkan hubungi kami di GitHub. 5 | ARSS™ 6 | Pengaturan 7 | Aplikasi ini membutuhkan perizinan 8 | Resolusi perangkatmu tidak didukung 9 | Layanan sedang dimuat… 10 | Siap digunakan 11 | - Tampilkan di aplikasi lain\nBerguna agar aplikasi bisa dijalankan secara floating 12 | Terhubung ke ARSS™ 13 | Terputus dari ARSS™ 14 | Keluar 15 | Min 16 | Petunjuk untuk Recruitment 17 | Setel ulang 18 | Tidak ada Operator yang cocok 19 | Kemungkinan Operator yang didapat 20 | Atur waktu 3:50 untuk tag Robot dan dapatkan operator ★1 21 | Kemungkinan dapat ★4 atau yang lebih tinggi nih! 22 | Kemungkinan dapat ★5 atau yang lebih tinggi nih! 23 | Set Top Operator dengan waktu 9 Jam dan selamat! anda mendapatkan ★6 Baru! 24 | Waktu berjalan ARGS™ 25 | %d min 26 | 27 | Atur waktu untuk %s 28 | Mode malam 29 | Mohon mulai ARGS™ 30 | ARGS™ mulai menekan 31 | ARGS™ selesai 32 | ARGS™ sedang berjalan, %d min keluar 33 | Perangkatmu (%1$d×%2$d resolusi) belum mendukung ARGS™, tolong hubungi kami di GitHub. \nARSS™ tersedia tanpa terpengaruh. 34 | Tentang 35 | Donasi 36 | Anda dapat menunjukkan rasa terima kasih ke developer dengan cara donasi loh! 37 | Terima kasih atas donasimu, Doctor 38 | Beri rating aplikasi ini 39 | Beri rating aplikasi ini di Store anda 40 | Bergabung dalam diskusi kami 41 | Kamu bisa periksa di GitHub kami 42 | Berkontribusi ke ArkTap 43 | Masukkan Issues dan Pull Request ke GitHub kami 44 | Versi terinstal 45 | Memeriksa pembaruan… 46 | Memeriksa pembaruan gagal! 47 | Versi yang terinstal adalah versi terbaru 48 | Versi terbaru telah tersedia! 49 | Tipe versi 50 | Tipe versi telah berubah, mohon install ulang aplikasi 51 | Pembaruan 52 | Mengerti 53 | Oke 54 | Tidak, terima kasih 55 | Jangan sekarang 56 | Terjadi ERROR 57 | Coming soon 58 | Pemeriksaan otomatis 59 | Memeriksa pembaruan sesuai dengan jadwal 60 | Anda dapat memeriksa pembaruan di menu "Tentang" 61 | Menjalankan game 62 | Menjalankan game jika perlu 63 | Server Game 64 | Diurutkan menaik 65 | Urutkan operator berdasarkan ★ dalam urutan menaik 66 | Tampilkan yang belum dirilis 67 | Tampilkan operator yang belum dirilis di server saat ini 68 | Navigasi cepat 69 | Gulir ke area hasil setelah memilih 5 tag 70 | Terima kasih khusus 71 | Penghitung Headhunt 72 | Roll: %1$d\nKemungkinan 6 ★ diroll berikutnya: %2$d%%\nTekan lama + untuk x10, - untuk membersihkan 73 | Reset data yang diunduh? 74 | Reset berhasil 75 | Data terbaru diperbarui 76 | Petunjuk Material 77 | Double Speed 78 | Beroperasi dengan Double Speed 79 | Data dari Penguin Statistics, hanya untuk referensi 80 | %s > Workshop 81 | %1$s | %2$.1f%% | %3$.1f Sanity 82 | Standard headhunt 83 | Limited headhunt 84 | Translucent sprite 85 | Mengurangi penggunaan memori 86 | Dimulai ketika membuka Aksesibilitas, dan menghentikan fitur aksesibilitas setelah selesai. 87 | Akses root diperlukan 88 | Detail 89 | ARGS™ tidak dapat dimulai karena akses Aksesibilitas telah di matikan, mohon install ulang aplikasi. 90 | Tidak dapat menemukan ARGS™ di menu aksesibilitas? tekan disini 91 | Install ulang 92 | Bagikan 93 | Support 94 | Tekan Volume bawah untuk menghentikan 95 | Kustomisasi Points 96 | Format Salah 97 | 额外点击坐标 98 | 防止嗑药碎石和结算循环 99 | Penguin Statistics 100 | PRTS Wiki 101 | Alipay 102 | WeChat Pay 103 | PayPal 104 | Penyumbang 105 | Penerjemah 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/values-ja/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ArkTap 3 | ARGS™ 4 | ARGS™を使って、ステージの周回を自動化にすることができます。\n\n開始する前にステージを選び、代理指揮にチェックを入れてから始めてください。\n\n本サービスの使用によるユーザーのアカウントが異常と判別されることがあります。これによって発生した如何なる損害に本アプリ及び開発者は責任を負いかねます。\n\nARGS™を使用する際に請求するアクセス権限はあくまでも機能実現のためであり、これを通してユーザーの個人情報収集は一切ございません。\n\nトラブルやコメントがあれば、ぜひレポートをお願いします。 5 | ARSS™ 6 | 設定 7 | アクセス権限の請求 8 | デバイスはサポートされていません 9 | 起動中… 10 | 起動完了、始めましょう 11 | - 他のアプリの上に重ねて表示する権限\n操作ボタンに必要です 12 | ARSS™接続込み 13 | ARSS™接続解除 14 | 解除 15 | 最小化 16 | 公開求人シミュレータ 17 | リセット 18 | タグを満たすキャラは存在しません 19 | 獲得可能なキャラ 20 | レア! 短時間の募集で★1のロボットを獲得可能 21 | ★4以上のキャラを獲得可能 22 | レア! ★5のキャラを獲得可能 23 | ~~~㊗激レア!!! ‘上級エリート’タグを選択し、求人時間を9時間にすれば必ず★6のキャラが貰えます㊗~~~ 24 | 作動時間 25 | %d分間 26 | 制限なし 27 | 作動時間は%sに設定しました 28 | ダークテーマ 29 | ARGS™をONにしてください 30 | ARGS™開始 31 | ARGS™終了 32 | ARGS™作動中,残り%d分 33 | ARGS™はまだ解像度%1$d×%2$dに対応していません。レポートをしてください。\n公開求人の企画等の機能には影響しません。 34 | ArkTapについて 35 | 寄付について 36 | 寄付をして頂ければ幸いです。 37 | 寄付をしていただきありがとうございます。これからもどうぞ宜しくお願いします。 38 | アプリレビュー 39 | 好評価をお願いします 40 | チャットグループ 41 | 最新情報はGithubで確認できます 42 | プロジェクトページ 43 | GitHubでレポートをする 44 | 現在のバージョン 45 | アップデートをチェック中… 46 | アップデートのチェックが失敗 47 | 既に最新バージョンにアップデート込み 48 | 新しいアップデートを発見 49 | バージョンタイプ 50 | Version type changed, please reinstall app 51 | アップデート 52 | 了解 53 | 許可する 54 | 拒否する 55 | また今度 56 | エラー発生 57 | 乞うご期待 58 | アプリの自動アップデート 59 | 定期的にアップデートチェックをする 60 | ‘ArkTapについて’でのアップデートチェックも可能 61 | ゲームを起動する 62 | 必要時にゲームを自動起動する 63 | サーバー選択 64 | 並び替え 65 | 低レア順に並び替える 66 | 未実装のキャラを加える 67 | 選択したサーバーで未実装キャラを加える 68 | オートスライディング 69 | 5つのタグを選び終えたら下方にスライドする 70 | 特別感謝 71 | ガチャカウンタ 72 | ガチャ回数:%1$d回\n次回★6入手確率:%2$d%%\n+を長押し→十連ガチャ\n−を長押し→リセット 73 | ダウンロードしたアップデートデータをリセットしますか? 74 | アップデートデータをリセットしました 75 | 既に最新のデータにアップデート 76 | 素材周回オススメ 77 | 倍速行動 78 | 2倍速でタップ 79 | データはPenguin Statisticsから。ご参考に。 80 | %s > 加工所 81 | %1$s | %2$.1f%% | %3$.1f理性 82 | 標準ガチャ 83 | 限定ガチャ 84 | 操作ボタンを半透明に 85 | 减少内存占用 86 | 打开无障碍后开始,结束后关闭无障碍 87 | Root is required. 88 | 詳細情報 89 | Accessibility was killed, please reinstall app 90 | ARGS™ not found in Accessibity? Click here 91 | Reinstall 92 | Share 93 | Support 94 | Volume down to stop 95 | Customize points 96 | Wrong format 97 | 额外点击坐标 98 | 防止嗑药碎石和结算循环 99 | Penguin Statistics 100 | PRTS Wiki 101 | Alipay 102 | WeChat Pay 103 | PayPal 104 | 寄稿者 105 | 翻訳 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | @color/color_secondary_night 3 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/xml/accessibility_config.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/xml/filepaths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/xml/root_preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 18 | 19 | 24 | 25 | 28 | 29 | 30 | 31 | 37 | 38 | 43 | 44 | 48 | 49 | 50 | 53 | 54 | 58 | 59 | 64 | 65 | 69 | 70 | 74 | 75 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id("com.android.application") version "8.0.1" apply false 4 | kotlin("android") version "1.8.20" apply false 5 | } -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 |

Features

2 |

ARSS™

3 |

You can use it in game by a floating window.

4 |

Recruit Guide

5 |

Show possible operators in recruitment and help you choose the best combination of tags.

6 |

Headhunt Counter

7 |

Count the rolls of headhunt and show the possibility of 6★.

8 |

Material Guide

9 |

Recommend missions of elite materials.

10 |

ARGS™

11 |

Tap Version type 15 times in About to unlock this service

12 |

Tap the mission start button automatically. In that way you can put down your phone and do something more meaningful.

13 | -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/fastlane/metadata/android/en-US/images/icon.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | Arknights helper app -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/title.txt: -------------------------------------------------------------------------------- 1 | ArkTap -------------------------------------------------------------------------------- /fastlane/metadata/android/zh-CN/full_description.txt: -------------------------------------------------------------------------------- 1 |

功能

2 |

帮帮忙™

3 |

一个提供各种实用功能的悬浮球,可从通知栏“快速设置”图块打开。

4 |
公开招募规划
5 |

使用5个需求标签组合出可能的方案。

6 |
    7 |
  • 多渠道不同干员进度,明日方舟(含哔哩哔哩和龍成網路客户端)、Arknights 、アークナイツ 和 명일방주 随心切换,无需更改系统语言
  • 8 |
  • 支持招募时限选择
  • 9 |
  • 触摸标题时隐藏内容,抬起重置标签
  • 10 |
11 |
寻访计数器
12 |

记录已寻访次数并获取下次获得6★概率。

13 |
材料来源推荐
14 |

提供养成材料的高性价比掉落关卡。

15 |

戳戳乐™

16 |

在关于界面一直戳“版本类型”,更新为 Originium 后覆盖安装应用或重启设备即可解除封印

17 |

可选择非剿灭作战关卡持续进行代理作战,解放双手,不用一直盯着屏幕。

18 |
    19 |
  • Android 7.0 及更高版本基于无障碍 API 实现,无需 ADB 或 Root 权限
  • 20 |
  • 不截取屏幕内容,支持多分辨率
  • 21 |
  • 可设置行动间隔和时长,自带波动间隔(±150ms)和偏移坐标(±5px)点击
  • 22 |
  • 首页长按图标可自定义坐标
  • 23 |
24 | -------------------------------------------------------------------------------- /fastlane/metadata/android/zh-CN/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/fastlane/metadata/android/zh-CN/images/icon.png -------------------------------------------------------------------------------- /fastlane/metadata/android/zh-CN/short_description.txt: -------------------------------------------------------------------------------- 1 | 辅助博士们游玩明日方舟的应用 -------------------------------------------------------------------------------- /fastlane/metadata/android/zh-CN/title.txt: -------------------------------------------------------------------------------- 1 | 方舟帮帮忙 -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | android.defaults.buildfeatures.buildconfig=true 23 | # Enables namespacing of each library's R class so that its R class includes only the 24 | # resources declared in the library itself and none from the library's dependencies, 25 | # thereby reducing the size of the R class for that library 26 | android.nonTransitiveRClass=false 27 | android.nonFinalResIds=false 28 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aistra0528/ArknightsTap/b9274f4b04c39728e83ef8e436f2310108bc81c8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Apr 16 14:14:36 CST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "ArknightsTap" 16 | include(":app") 17 | -------------------------------------------------------------------------------- /signing.properties.sample: -------------------------------------------------------------------------------- 1 | storeFile=filename.keystore 2 | storePassword=password 3 | keyAlias=alias 4 | keyPassword=password --------------------------------------------------------------------------------