├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── kotlinc.xml ├── misc.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle.kts ├── libs │ └── fastjson-1.2.9.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── wx.png │ └── zfb.jpg │ ├── ic_launcher_xplan-playstore.png │ ├── java │ └── com │ │ └── itos │ │ └── xplanforhyper │ │ ├── CardWidget.kt │ │ ├── XPlanForHyper.kt │ │ ├── datatype │ │ ├── AppInfo.kt │ │ ├── ConfigData.kt │ │ └── OriginCardItem.kt │ │ ├── ui │ │ ├── Pages │ │ │ ├── AboutPage.kt │ │ │ ├── OptPage.kt │ │ │ └── subassemblies │ │ │ │ ├── About │ │ │ │ ├── DiscussWidget.kt │ │ │ │ ├── DonateWidget.kt │ │ │ │ ├── OpenSourceWidget.kt │ │ │ │ └── StatusWidget.kt │ │ │ │ └── Opt │ │ │ │ ├── ControlSystemUpdateButton.kt │ │ │ │ ├── HDButton.kt │ │ │ │ ├── OptButton.kt │ │ │ │ ├── ProcessLimitButton.kt │ │ │ │ └── SettingsOptButton.kt │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ │ └── utils │ │ ├── NetUtils.java │ │ ├── OData.kt │ │ ├── OLog.kt │ │ ├── OPackage.kt │ │ ├── OShizuku.kt │ │ ├── OTarget.kt │ │ ├── OUI.kt │ │ └── SpUtils.java │ └── res │ ├── drawable │ ├── ic_alipay.xml │ ├── ic_baseline_info.xml │ ├── ic_baseline_terminal.xml │ ├── ic_bilibili.xml │ ├── ic_launcher_background.xml │ ├── ic_launcher_foreground.xml │ ├── ic_outline_code.xml │ ├── ic_outline_coolapk.xml │ ├── ic_outline_giftcard.xml │ ├── ic_outline_info.xml │ ├── ic_outline_lisence.xml │ ├── ic_outline_qq.xml │ └── ic_wechatpay.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher_xplan.xml │ └── ic_launcher_xplan_round.xml │ ├── mipmap-anydpi │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.webp │ ├── ic_launcher_round.webp │ ├── ic_launcher_xplan.png │ ├── ic_launcher_xplan_foreground.png │ └── ic_launcher_xplan_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.webp │ ├── ic_launcher_round.webp │ ├── ic_launcher_xplan.png │ ├── ic_launcher_xplan_foreground.png │ └── ic_launcher_xplan_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_round.webp │ ├── ic_launcher_xplan.png │ ├── ic_launcher_xplan_foreground.png │ └── ic_launcher_xplan_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_round.webp │ ├── ic_launcher_xplan.png │ ├── ic_launcher_xplan_foreground.png │ └── ic_launcher_xplan_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_round.webp │ ├── ic_launcher_xplan.png │ ├── ic_launcher_xplan_foreground.png │ └── ic_launcher_xplan_round.png │ ├── raw │ ├── licenses │ ├── moreapp │ ├── optlist │ └── pkglist │ ├── values │ ├── colors.xml │ ├── ic_launcher_xplan_background.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── app_config.json ├── app_update.json ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 124 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | id("org.jetbrains.kotlin.android") 4 | } 5 | 6 | android { 7 | namespace = "com.itos.xplanforhyper" 8 | compileSdk = 34 9 | applicationVariants.all { 10 | outputs.all { 11 | val ver = defaultConfig.versionName+"(${defaultConfig.versionCode})" 12 | 13 | (this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName = 14 | "XHpyer_$ver.apk" 15 | } 16 | } 17 | defaultConfig { 18 | applicationId = "com.itos.xplanforhyper" 19 | minSdk = 26 20 | targetSdk = 34 21 | versionCode = 5 22 | versionName = "1.1" 23 | 24 | // testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 25 | vectorDrawables { 26 | useSupportLibrary = true 27 | } 28 | 29 | buildTypes { 30 | release { 31 | isMinifyEnabled = true 32 | proguardFiles( 33 | getDefaultProguardFile("proguard-android-optimize.txt"), 34 | "proguard-rules.pro" 35 | ) 36 | } 37 | } 38 | compileOptions { 39 | sourceCompatibility = JavaVersion.VERSION_1_8 40 | targetCompatibility = JavaVersion.VERSION_1_8 41 | } 42 | kotlinOptions { 43 | jvmTarget = "1.8" 44 | } 45 | buildFeatures { 46 | compose = true 47 | aidl=true 48 | buildConfig=true 49 | } 50 | composeOptions { 51 | kotlinCompilerExtensionVersion = "1.4.3" 52 | } 53 | packaging { 54 | resources { 55 | excludes += "/META-INF/{AL2.0,LGPL2.1}" 56 | } 57 | } 58 | 59 | } 60 | buildTypes { 61 | getByName("release") { 62 | isMinifyEnabled = true 63 | } 64 | } 65 | } 66 | 67 | dependencies { 68 | implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2") 69 | 70 | implementation("dev.rikka.shizuku:api:13.1.0") 71 | implementation("dev.rikka.shizuku:provider:13.1.0") 72 | implementation("androidx.compose.material3:material3") 73 | implementation("androidx.core:core-ktx:1.12.0") 74 | implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") 75 | implementation("androidx.activity:activity-compose:1.8.2") 76 | implementation(platform("androidx.compose:compose-bom:2023.03.00")) 77 | implementation("androidx.compose.ui:ui") 78 | implementation("androidx.compose.ui:ui-graphics") 79 | implementation("androidx.compose.ui:ui-tooling-preview") 80 | implementation("androidx.navigation:navigation-compose:2.7.6") 81 | implementation("androidx.compose.material:material:1.6.0") 82 | implementation("com.google.accompanist:accompanist-drawablepainter:0.20.0") 83 | implementation(files("libs/fastjson-1.2.9.jar")) 84 | implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3") 85 | implementation("com.google.android.material:material:1.11.0") 86 | implementation("com.google.accompanist:accompanist-systemuicontroller:0.27.0") 87 | // testImplementation("junit:junit:4.13.2") 88 | // androidTestImplementation("androidx.test.ext:junit:1.1.5") 89 | // androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") 90 | // androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) 91 | // androidTestImplementation("androidx.compose.ui:ui-test-junit4") 92 | debugImplementation("androidx.compose.ui:ui-tooling") 93 | debugImplementation("androidx.compose.ui:ui-test-manifest") 94 | } -------------------------------------------------------------------------------- /app/libs/fastjson-1.2.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/libs/fastjson-1.2.9.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | # 指定代码的压缩级别 23 | -optimizationpasses 5 24 | 25 | # 不忽略库中的非public的类成员 26 | -dontskipnonpubliclibraryclassmembers 27 | 28 | # google推荐算法 29 | -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* 30 | 31 | # 避免混淆Annotation、内部类、泛型、匿名类 32 | -keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod 33 | 34 | # 抛出异常时保留代码行号 35 | -keepattributes SourceFile,LineNumberTable 36 | -keep class android.content.pm.IPackageManager { 37 | *; 38 | } 39 | -dontwarn java.awt.Color 40 | -dontwarn java.awt.Font 41 | -dontwarn java.awt.Point 42 | -dontwarn java.awt.Rectangle 43 | 44 | # 保持四大组件 45 | -keep public class * extends android.app.Activity 46 | -keep public class * extends android.app.Application 47 | -keep public class * extends android.app.Service 48 | -keep public class * extends android.content.BroadcastReceiver 49 | -keep public class * extends android.content.ContentProvider 50 | -keep public class * extends android.app.backup.BackupAgentHelper 51 | -keep public class * extends android.preference.Preference 52 | -keep public class * extends android.view.View 53 | -keep public class com.android.vending.licensing.ILicensingService 54 | 55 | # 保持support下的所有类及其内部类 56 | -keep class android.support.** {*;} 57 | 58 | # 保留继承的 59 | -keep public class * extends android.support.v4.** 60 | -keep public class * extends android.support.v7.** 61 | -keep public class * extends android.support.annotation.** 62 | 63 | # 保持自定义控件 64 | -keep public class * extends android.view.View{ 65 | *** get*(); 66 | void set*(***); 67 | public (android.content.Context); 68 | public (android.content.Context, android.util.AttributeSet); 69 | public (android.content.Context, android.util.AttributeSet, int); 70 | } 71 | 72 | # 保持所有实现 Serializable 接口的类成员 73 | -keepclassmembers class * implements java.io.Serializable { 74 | static final long serialVersionUID; 75 | private static final java.io.ObjectStreamField[] serialPersistentFields; 76 | private void writeObject(java.io.ObjectOutputStream); 77 | private void readObject(java.io.ObjectInputStream); 78 | java.lang.Object writeReplace(); 79 | java.lang.Object readResolve(); 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/assets/wx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/assets/wx.png -------------------------------------------------------------------------------- /app/src/main/assets/zfb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/assets/zfb.jpg -------------------------------------------------------------------------------- /app/src/main/ic_launcher_xplan-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/ic_launcher_xplan-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/CardWidget.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.foundation.clickable 2 | import androidx.compose.foundation.layout.Arrangement 3 | import androidx.compose.foundation.layout.Box 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.Row 6 | import androidx.compose.foundation.layout.Spacer 7 | import androidx.compose.foundation.layout.fillMaxWidth 8 | import androidx.compose.foundation.layout.padding 9 | import androidx.compose.foundation.layout.size 10 | import androidx.compose.material3.CardColors 11 | import androidx.compose.material3.CardDefaults 12 | import androidx.compose.material3.ElevatedCard 13 | import androidx.compose.material3.Icon 14 | import androidx.compose.material3.LocalContentColor 15 | import androidx.compose.material3.MaterialTheme 16 | import androidx.compose.material3.ProvideTextStyle 17 | import androidx.compose.material3.Text 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.runtime.CompositionLocalProvider 20 | import androidx.compose.ui.Alignment 21 | import androidx.compose.ui.Modifier 22 | import androidx.compose.ui.unit.dp 23 | import com.itos.xplanforhyper.datatype.OriginCardItem 24 | 25 | @Composable 26 | fun ItemsCardWidget( 27 | colors: CardColors = CardDefaults.elevatedCardColors(), 28 | onClick: (() -> Unit)? = null, 29 | showItemIcon: Boolean = false, 30 | icon: (@Composable () -> Unit)? = null, 31 | title: (@Composable () -> Unit)? = null, 32 | items: List, 33 | buttons: (@Composable () -> Unit)? = null 34 | ) { 35 | CardWidget( 36 | colors = colors, 37 | onClick = onClick, 38 | icon = icon, 39 | title = title, 40 | content = { 41 | @Composable 42 | fun ItemWidget(item: OriginCardItem) { 43 | Row( 44 | modifier = Modifier 45 | .clickable(enabled = item.onClick != null, onClick = item.onClick ?: {}) 46 | .padding(horizontal = 24.dp, vertical = 12.dp), 47 | horizontalArrangement = Arrangement.spacedBy(24.dp) 48 | ) { 49 | if (showItemIcon) { 50 | if (item.icon != null) { 51 | Icon(imageVector = item.icon, contentDescription = item.label) 52 | } else { 53 | Spacer(modifier = Modifier.size(32.dp)) 54 | } 55 | } 56 | Column( 57 | modifier = Modifier 58 | .weight(1f) 59 | ) { 60 | Text(text = item.label, style = MaterialTheme.typography.bodyLarge) 61 | if (item.content != null) { 62 | Text( 63 | text = item.content, 64 | style = MaterialTheme.typography.bodyMedium 65 | ) 66 | } 67 | } 68 | } 69 | } 70 | Column { 71 | items.forEach { 72 | ItemWidget(it) 73 | } 74 | } 75 | }, 76 | buttons = buttons 77 | ) 78 | } 79 | 80 | @Composable 81 | fun CardWidget( 82 | colors: CardColors = CardDefaults.elevatedCardColors(), 83 | onClick: (() -> Unit)? = null, 84 | icon: (@Composable () -> Unit)? = null, 85 | title: (@Composable () -> Unit)? = null, 86 | content: (@Composable () -> Unit)? = null, 87 | buttons: (@Composable () -> Unit)? = null 88 | ) { 89 | ElevatedCard( 90 | colors = colors, 91 | elevation = CardDefaults.elevatedCardElevation(defaultElevation = 5.dp) 92 | ) { 93 | Column( 94 | modifier = Modifier 95 | .fillMaxWidth() 96 | .clickable(enabled = onClick != null, onClick = onClick ?: {}) 97 | .padding(vertical = 24.dp), 98 | verticalArrangement = Arrangement.spacedBy(4.dp) 99 | ) { 100 | if (icon != null) { 101 | CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.secondary) { 102 | Box(modifier = Modifier.align(Alignment.CenterHorizontally)) { 103 | icon() 104 | } 105 | } 106 | } 107 | if (title != null) { 108 | ProvideTextStyle(value = MaterialTheme.typography.titleLarge) { 109 | Box(modifier = Modifier.align(Alignment.CenterHorizontally)) { 110 | title() 111 | } 112 | } 113 | } 114 | if (content != null) { 115 | Box { 116 | content() 117 | } 118 | } 119 | if (buttons != null) { 120 | Box { 121 | buttons() 122 | } 123 | } 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/XPlanForHyper.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper 2 | 3 | import AboutPage 4 | import android.annotation.SuppressLint 5 | import android.content.ClipData 6 | import android.content.ClipboardManager 7 | import android.content.Context 8 | import android.content.Intent 9 | import android.content.pm.ApplicationInfo 10 | import android.content.pm.PackageManager 11 | import android.content.res.Configuration 12 | import android.net.Uri 13 | import android.os.Build 14 | import android.os.Bundle 15 | import android.text.InputType 16 | import android.widget.EditText 17 | import android.widget.Toast 18 | import androidx.activity.compose.setContent 19 | import androidx.appcompat.app.AppCompatActivity 20 | import androidx.compose.foundation.Image 21 | import androidx.compose.foundation.background 22 | import androidx.compose.foundation.layout.Arrangement 23 | import androidx.compose.foundation.layout.Column 24 | import androidx.compose.foundation.layout.Row 25 | import androidx.compose.foundation.layout.fillMaxSize 26 | import androidx.compose.foundation.layout.fillMaxWidth 27 | import androidx.compose.foundation.layout.padding 28 | import androidx.compose.foundation.layout.size 29 | import androidx.compose.foundation.lazy.LazyColumn 30 | import androidx.compose.foundation.lazy.items 31 | import androidx.compose.material.icons.Icons 32 | import androidx.compose.material.icons.filled.Check 33 | import androidx.compose.material.icons.filled.Close 34 | import androidx.compose.material.icons.filled.Create 35 | import androidx.compose.material.icons.filled.Delete 36 | import androidx.compose.material.icons.filled.Info 37 | import androidx.compose.material.icons.filled.MoreVert 38 | import androidx.compose.material.icons.filled.Refresh 39 | import androidx.compose.material.icons.filled.Settings 40 | import androidx.compose.material.icons.filled.Warning 41 | import androidx.compose.material.icons.outlined.Create 42 | import androidx.compose.material.icons.outlined.Info 43 | import androidx.compose.material.icons.outlined.Settings 44 | import androidx.compose.material3.DropdownMenu 45 | import androidx.compose.material3.DropdownMenuItem 46 | import androidx.compose.material3.ExperimentalMaterial3Api 47 | import androidx.compose.material3.Icon 48 | import androidx.compose.material3.IconButton 49 | import androidx.compose.material3.LocalContentColor 50 | import androidx.compose.material3.MaterialTheme 51 | import androidx.compose.material3.NavigationBar 52 | import androidx.compose.material3.NavigationBarItem 53 | import androidx.compose.material3.Scaffold 54 | import androidx.compose.material3.Surface 55 | import androidx.compose.material3.Text 56 | import androidx.compose.material3.TopAppBar 57 | import androidx.compose.runtime.Composable 58 | import androidx.compose.runtime.MutableState 59 | import androidx.compose.runtime.RecomposeScope 60 | import androidx.compose.runtime.currentRecomposeScope 61 | import androidx.compose.runtime.getValue 62 | import androidx.compose.runtime.mutableStateOf 63 | import androidx.compose.runtime.remember 64 | import androidx.compose.runtime.setValue 65 | import androidx.compose.ui.Alignment 66 | import androidx.compose.ui.Modifier 67 | import androidx.compose.ui.graphics.Color 68 | import androidx.compose.ui.graphics.vector.ImageVector 69 | import androidx.compose.ui.platform.LocalContext 70 | import androidx.compose.ui.res.vectorResource 71 | import androidx.compose.ui.tooling.preview.Preview 72 | import androidx.compose.ui.unit.dp 73 | import androidx.core.content.getSystemService 74 | import androidx.lifecycle.lifecycleScope 75 | import androidx.navigation.compose.NavHost 76 | import androidx.navigation.compose.composable 77 | import androidx.navigation.compose.currentBackStackEntryAsState 78 | import androidx.navigation.compose.rememberNavController 79 | import com.alibaba.fastjson.JSONObject 80 | import com.google.accompanist.drawablepainter.rememberDrawablePainter 81 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 82 | import com.google.android.material.textview.MaterialTextView 83 | import com.itos.xplanforhyper.datatype.AppInfo 84 | import com.itos.xplanforhyper.ui.theme.OriginPlanTheme 85 | import com.itos.xplanforhyper.utils.NetUtils 86 | import com.itos.xplanforhyper.utils.OData 87 | import com.itos.xplanforhyper.utils.OLog 88 | import com.itos.xplanforhyper.utils.OPackage 89 | import com.itos.xplanforhyper.utils.OPackage.getAppIconByPackageName 90 | import com.itos.xplanforhyper.utils.OShizuku 91 | import com.itos.xplanforhyper.utils.OShizuku.checkShizuku 92 | import com.itos.xplanforhyper.utils.OUI 93 | import com.itos.xplanforhyper.utils.SpUtils 94 | import kotlinx.coroutines.CoroutineExceptionHandler 95 | import kotlinx.coroutines.Dispatchers 96 | import kotlinx.coroutines.launch 97 | import kotlinx.coroutines.withContext 98 | import rikka.shizuku.Shizuku 99 | import rikka.shizuku.Shizuku.OnBinderReceivedListener 100 | import rikka.shizuku.ShizukuRemoteProcess 101 | import java.io.BufferedReader 102 | import java.io.InputStreamReader 103 | import java.io.OutputStream 104 | 105 | // TODO 拆Details页面 106 | 107 | class XPlanForHyper : AppCompatActivity() { 108 | val context: Context = this 109 | var ReturnValue = 0 110 | var br = false 111 | var h2: Thread? = null 112 | var h3: Thread? = null 113 | var b = true 114 | var c = false 115 | var show_notice: String = "暂无公告" 116 | 117 | // private var FirstTime_pf: SharedPreferences? = null 118 | private val pkglist = mutableListOf() 119 | val optlist = mutableListOf() 120 | 121 | private val requestPermissionResultListener = 122 | Shizuku.OnRequestPermissionResultListener { requestCode: Int, grantResult: Int -> 123 | this.onRequestPermissionsResult() 124 | } 125 | private val BINDER_RECEVIED_LISTENER = 126 | OnBinderReceivedListener { 127 | checkShizuku() 128 | } 129 | private val BINDER_DEAD_LISTENER: Shizuku.OnBinderDeadListener = 130 | Shizuku.OnBinderDeadListener { 131 | checkShizuku() 132 | } 133 | 134 | override fun onCreate(savedInstanceState: Bundle?) { 135 | super.onCreate(savedInstanceState) 136 | setContent { 137 | OriginPlanTheme { 138 | // A surface container using the 'background' color from the theme 139 | Surface( 140 | modifier = Modifier.fillMaxSize(), 141 | color = MaterialTheme.colorScheme.background 142 | ) { 143 | AppListContent() 144 | } 145 | } 146 | } 147 | load_applist() 148 | app = this 149 | 150 | Shizuku.addRequestPermissionResultListener(requestPermissionResultListener) 151 | // 3是a13,2是a12(service call),1是pm增强,0是pm 152 | when (Build.VERSION.SDK_INT) { 153 | Build.VERSION_CODES.TIRAMISU -> { 154 | SpUtils.setParam(context, "method", 3) 155 | } 156 | 157 | Build.VERSION_CODES.S, Build.VERSION_CODES.S_V2 -> { 158 | SpUtils.setParam(context, "method", 2) 159 | } 160 | 161 | else -> { 162 | SpUtils.setParam(context, "method", 1) 163 | } 164 | } 165 | checkShizuku() 166 | OUI.check_secure_premission() 167 | Shizuku.addBinderReceivedListenerSticky(BINDER_RECEVIED_LISTENER) 168 | Shizuku.addBinderDeadListener(BINDER_DEAD_LISTENER) 169 | guide() 170 | generateAppList(context) 171 | update_notice() 172 | } 173 | 174 | private fun load_applist() { 175 | lifecycleScope.launch(Dispatchers.IO) { 176 | try { 177 | // 打开 pkglistfile 文件输入流 178 | val inputStream_pkg = resources.openRawResource(R.raw.pkglist) 179 | val reader_pkg = BufferedReader(InputStreamReader(inputStream_pkg)) 180 | val inputStream_opt = resources.openRawResource(R.raw.optlist) 181 | val reader_opt = BufferedReader(InputStreamReader(inputStream_opt)) 182 | 183 | // 逐行读取文件内容 184 | var line_pkg: String? 185 | var line_opt: String? 186 | while (reader_pkg.readLine().also { line_pkg = it } != null) { 187 | val packageName = line_pkg!!.trim() 188 | // 创建 AppInfo 对象,并添加到列表 189 | val appInfo = AppInfo(appName = "", appPkg = packageName) 190 | pkglist.add(appInfo) 191 | } 192 | while (reader_opt.readLine().also { line_opt = it } != null) { 193 | val packageName = line_opt!!.trim() 194 | // 创建 AppInfo 对象,并添加到列表 195 | val appInfo = AppInfo(appName = "", appPkg = packageName) 196 | optlist.add(appInfo) 197 | } 198 | } catch (_: Exception) { 199 | } 200 | } 201 | 202 | } 203 | 204 | private fun guide() { 205 | if (SpUtils.getParam(context, "if_first_time", true) as Boolean) { 206 | MaterialAlertDialogBuilder(context) 207 | .setTitle("帮助") 208 | .setMessage("您需要Shiuzku激活教程吗") 209 | .setPositiveButton("好的") { dialog, which -> 210 | SpUtils.setParam(context, "if_first_time", false) 211 | OUI.openLink("https://www.bilibili.com/video/BV1o94y1u7Kq") 212 | } 213 | .setNegativeButton("我会") { dialog, which -> 214 | SpUtils.setParam(context, "if_first_time", false) 215 | dialog.dismiss() 216 | } 217 | .show() 218 | .setCancelable(false) 219 | } 220 | } 221 | 222 | private fun update_notice() { 223 | val handler = CoroutineExceptionHandler { _, exception -> 224 | // 在这里处理异常,例如打印日志、上报异常等 225 | OLog.e("Update Notice Exception:", exception) 226 | MaterialAlertDialogBuilder(context) 227 | .setTitle("错误") 228 | .setMessage("连接服务器失败\n请检查网络连接") 229 | .setPositiveButton("了解", null) 230 | .show() 231 | } 232 | lifecycleScope.launch(Dispatchers.IO + handler) { 233 | // 后台工作 234 | val update = NetUtils.Get(OData.updataUrl) 235 | // 切换到主线程进行 UI 操作 236 | withContext(Dispatchers.Main) { 237 | // UI 操作,例如显示 Toast 238 | val jsonObject = JSONObject.parseObject(update) 239 | val version = jsonObject.getString("version") 240 | val url = jsonObject.getString("url") 241 | val version_name = jsonObject.getString("version_name") 242 | val log = jsonObject.getString("log") 243 | val isShowNotice = jsonObject.getBoolean("isShowNotice") 244 | val notice = jsonObject.getString("notice") 245 | show_notice = notice 246 | OLog.i( 247 | "更新", 248 | update + "\n" + version + "\n" + url + "\n" + version_name + "\n" + log + "\n" + isShowNotice + "\n" + notice 249 | ) 250 | if (BuildConfig.VERSION_CODE < version.toInt()) { 251 | OLog.i("更新", "有新版本") 252 | MaterialAlertDialogBuilder(context) 253 | .setTitle("有新版本") 254 | .setMessage("最新版本:$version_name($version)\n\n更新日志:\n$log") 255 | .setPositiveButton("前往更新") { dialog, which -> 256 | OUI.openLink(url) 257 | finish() 258 | } 259 | .setCancelable(false) 260 | .show() 261 | } else { 262 | if (isShowNotice) { 263 | OLog.i("公告", "显示") 264 | MaterialAlertDialogBuilder(context) 265 | .setTitle("公告") 266 | .setMessage(notice) 267 | .setPositiveButton("我知道了") { dialog, which -> 268 | dialog.dismiss() 269 | } 270 | .show() 271 | } 272 | } 273 | 274 | } 275 | } 276 | } 277 | 278 | 279 | private fun onRequestPermissionsResult() { 280 | checkShizuku() 281 | } 282 | 283 | override fun onDestroy() { 284 | super.onDestroy() 285 | Shizuku.removeBinderReceivedListener(BINDER_RECEVIED_LISTENER) 286 | Shizuku.removeBinderDeadListener(BINDER_DEAD_LISTENER) 287 | Shizuku.removeRequestPermissionResultListener(requestPermissionResultListener) 288 | } 289 | 290 | private fun uninstall(appInfo: AppInfo, a: RecomposeScope) { 291 | 292 | MaterialAlertDialogBuilder(context) 293 | .setTitle("尝试卸载") 294 | .setMessage("您将卸载 ${appInfo.appName}(${appInfo.appPkg})") 295 | .setPositiveButton("确定") { _, _ -> 296 | val t: String? = when (SpUtils.getParam(context, "method", 1)) { 297 | 3 -> { 298 | ShizukuExec("service call package 131 s16 ${appInfo.appPkg} i32 0 i32 0".toByteArray()) 299 | } 300 | 301 | 2 -> { 302 | ShizukuExec("service call package 134 s16 ${appInfo.appPkg} i32 0 i32 0".toByteArray()) 303 | } 304 | 305 | 1 -> { 306 | ShizukuExec("pm uninstall --user 0 ${appInfo.appPkg}".toByteArray()) 307 | } 308 | 309 | else -> { 310 | ShizukuExec("pm uninstall ${appInfo.appPkg}".toByteArray()) 311 | } 312 | } 313 | MaterialAlertDialogBuilder(context) 314 | .setTitle("结果") 315 | .setMessage(t) 316 | .setPositiveButton("ok") { _, _ -> 317 | appInfo.isExist = 318 | OPackage.isInstalled(appInfo.appPkg, context.packageManager) 319 | appInfo.appName = getAppNameByPackageName(context, appInfo.appPkg) 320 | appInfo.appIcon = 321 | getAppIconByPackageName(appInfo.appPkg, context.packageManager) 322 | a.invalidate() 323 | } 324 | .show() 325 | } 326 | .setNegativeButton("取消") { _, _ -> } 327 | .show() 328 | } 329 | 330 | private fun reinstall(appInfo: AppInfo, a: RecomposeScope) { 331 | MaterialAlertDialogBuilder(context) 332 | .setTitle("尝试重装") 333 | .setMessage("您将尝试重装 ${appInfo.appPkg} ,此操作仅系统自带核心app可用") 334 | .setPositiveButton("确定") { _, _ -> 335 | Toast.makeText(context, "请稍等...", Toast.LENGTH_LONG).show() 336 | val t: String? = when (SpUtils.getParam(context, "method", 1)) { 337 | 3 -> { 338 | ShizukuExec("service call package 131 s16 ${appInfo.appPkg} i32 1 i32 0".toByteArray()) 339 | } 340 | 341 | 2 -> { 342 | ShizukuExec("service call package 134 s16 ${appInfo.appPkg} i32 1 i32 0".toByteArray()) 343 | } 344 | 345 | else -> { 346 | ShizukuExec("pm install-existing ${appInfo.appPkg}".toByteArray()) 347 | } 348 | } 349 | MaterialAlertDialogBuilder(context) 350 | .setTitle("结果") 351 | .setMessage(t) 352 | .setPositiveButton("ok") { _, _ -> 353 | //重载页面 354 | appInfo.isExist = 355 | OPackage.isInstalled(appInfo.appPkg, context.packageManager) 356 | if (appInfo.isExist) { 357 | appInfo.isDisabled = isAppDisabled(appInfo.appPkg) 358 | appInfo.appName = getAppNameByPackageName(context, appInfo.appPkg) 359 | appInfo.appIcon = 360 | getAppIconByPackageName(appInfo.appPkg, context.packageManager) 361 | a.invalidate() 362 | } 363 | } 364 | .show() 365 | } 366 | .setNegativeButton("取消") { _, _ -> } 367 | .show() 368 | 369 | } 370 | 371 | fun patchProcessLimit() { 372 | MaterialAlertDialogBuilder(app) 373 | .setTitle("关闭缓存进程和虚进程数量限制") 374 | .setMessage("该操作可能导致卡米,您确定要进行吗?") 375 | .setPositiveButton("确定") { _, _ -> 376 | Toast.makeText(context, "请稍等...", Toast.LENGTH_LONG).show() 377 | ShizukuExec("device_config set_sync_disabled_for_tests persistent;device_config put activity_manager max_cached_processes 2007;device_config put activity_manager max_phantom_processes 2007;echo success".toByteArray()) 378 | MaterialAlertDialogBuilder(context) 379 | .setTitle("关闭缓存进程和虚进程数量限制") 380 | .setMessage("调整完成,是否立即重启") 381 | .setPositiveButton("立即重启") { _, _ -> 382 | ShizukuExec("reboot".toByteArray()) 383 | } 384 | .setNegativeButton("暂不重启") { _, _ -> } 385 | .show() 386 | } 387 | .setNegativeButton("取消",null) 388 | .show() 389 | } 390 | 391 | fun unpatchProcessLimit() { 392 | Toast.makeText(context, "请稍等...", Toast.LENGTH_LONG).show() 393 | ShizukuExec("device_config set_sync_disabled_for_tests none;device_config put activity_manager max_cached_processes 32;device_config put activity_manager max_phantom_processes 32".toByteArray()) 394 | MaterialAlertDialogBuilder(context) 395 | .setTitle("还原缓存进程和虚进程数量限制") 396 | .setMessage("还原完成,是否立即重启") 397 | .setPositiveButton("立即重启") { _, _ -> 398 | ShizukuExec("reboot".toByteArray()) 399 | } 400 | .setNegativeButton("暂不重启") { _, _ -> } 401 | .show() 402 | } 403 | 404 | fun ShizukuExec(cmd: ByteArray): String? { 405 | if (br) { 406 | return "正在执行其他操作" 407 | } 408 | if (!b || !c) { 409 | Toast.makeText(context, "Shizuku 状态异常", Toast.LENGTH_SHORT).show() 410 | return "Shizuku 状态异常" 411 | } 412 | br = true 413 | 414 | val p: ShizukuRemoteProcess 415 | val op = arrayOfNulls(1) 416 | try { 417 | OLog.i("运行shell", "开始运行$cmd") 418 | p = Shizuku.newProcess(arrayOf("sh"), null, null) 419 | val out: OutputStream = p.outputStream 420 | out.write(cmd) 421 | out.flush() 422 | out.close() 423 | h2 = Thread { 424 | try { 425 | val outText = StringBuilder() 426 | val reader = BufferedReader(InputStreamReader(p.inputStream)) 427 | var line: String? 428 | while (reader.readLine().also { line = it } != null) { 429 | outText.append(line).append("\n") 430 | } 431 | reader.close() 432 | val output = outText.toString() 433 | OLog.i("运行shell", "Output_Normal:\n$output") 434 | op[0] = output 435 | } catch (ignored: java.lang.Exception) { 436 | } 437 | } 438 | h2!!.start() 439 | h3 = Thread { 440 | try { 441 | val outText = StringBuilder() 442 | val reader = BufferedReader(InputStreamReader(p.getErrorStream())) 443 | var line: String? 444 | while (reader.readLine().also { line = it } != null) { 445 | outText.append(line).append("\n") 446 | } 447 | reader.close() 448 | val output = outText.toString() 449 | op[0] += output 450 | OLog.i("运行shell", "Output_Error:\n$output") 451 | } catch (ignored: java.lang.Exception) { 452 | } 453 | } 454 | h3!!.start() 455 | 456 | p.waitFor() 457 | h2!!.join() 458 | ReturnValue = p.exitValue() 459 | OLog.i("运行shell", "跑完了") 460 | p.destroyForcibly() 461 | br = false 462 | 463 | return op[0] 464 | } catch (ignored: java.lang.Exception) { 465 | } 466 | return "null" 467 | } 468 | 469 | fun SetAppDisabled( 470 | isDisabled: MutableState, 471 | packagename: String, 472 | isExist: Boolean, 473 | isShowToast: Boolean = true, 474 | appinfolist: MutableState? = null 475 | ): Boolean? { 476 | if (isExist) { 477 | OShizuku.setAppDisabled(packagename, !isDisabled.value) 478 | val c = isAppDisabled(packagename) 479 | if (c != isDisabled.value) { 480 | if (appinfolist != null) appinfolist.value.isDisabled = c 481 | isDisabled.value = c 482 | return true 483 | } else { 484 | if (isShowToast) { 485 | Toast.makeText(this, "设置失败", Toast.LENGTH_SHORT).show() 486 | } 487 | return false 488 | } 489 | } else { 490 | Toast.makeText(this, "应用未安装", Toast.LENGTH_SHORT).show() 491 | return null 492 | } 493 | } 494 | 495 | 496 | private fun getAppNameByPackageName(context: Context, packageName: String): String { 497 | val packageManager: PackageManager = context.packageManager 498 | val applicationInfo: ApplicationInfo? = try { 499 | packageManager.getApplicationInfo(packageName, 0) 500 | } catch (e: PackageManager.NameNotFoundException) { 501 | null 502 | } 503 | 504 | return applicationInfo?.let { 505 | packageManager.getApplicationLabel(it).toString() 506 | } ?: "未安装" 507 | } 508 | 509 | 510 | /**************** 511 | * 512 | * 发起添加群流程。群号:IQOO⭐️交流群(262040855) 的 key 为: SqLJvDGqjKNDvc_O5dx6A164eLSo4QBG 513 | * 调用 joinQQGroup(SqLJvDGqjKNDvc_O5dx6A164eLSo4QBG) 即可发起手Q客户端申请加群 IQOO⭐️交流群(262040855) 514 | * 515 | * @param key 由官网生成的key 516 | * @return 返回true表示呼起手Q成功,返回false表示呼起失败 517 | */ 518 | private fun joinQQGroup(key: String): Boolean { 519 | val intent = Intent() 520 | intent.data = 521 | Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26jump_from%3Dwebapi%26k%3D$key") 522 | // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 523 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 524 | return try { 525 | startActivity(intent) 526 | true 527 | } catch (e: java.lang.Exception) { 528 | // 未安装手Q或安装的版本不支持 529 | false 530 | } 531 | } 532 | 533 | private fun join_qq() { 534 | val is_join_succeed = joinQQGroup("SqLJvDGqjKNDvc_O5dx6A164eLSo4QBG") 535 | if (!is_join_succeed) { 536 | Toast.makeText( 537 | this, 538 | "未安装手Q或安装的版本不支持, 请手动加群262040855", 539 | Toast.LENGTH_LONG 540 | ).show() 541 | } 542 | } 543 | 544 | fun isAppDisabled(appPackageName: String): Boolean { 545 | val packageManager: PackageManager = context.packageManager 546 | 547 | val packageInfo = packageManager.getPackageInfo(appPackageName, 0) 548 | // 应用被停用或者处于默认状态(未设置启用状态),返回 true;其他状态返回 false 549 | return !packageInfo.applicationInfo.enabled 550 | } 551 | 552 | 553 | @Composable 554 | fun AppListItem(appinfo: AppInfo) { 555 | //让 compose监听这个的变化 556 | var appInfo = remember { mutableStateOf(appinfo) } 557 | val isDisabled = remember { mutableStateOf(appInfo.value.isDisabled) } 558 | // val appinfo_remember=remember{ mutableStateOf(appInfo) } 559 | // val refreshing = remember { mutableStateOf(false) } 560 | var isMenuVisible by remember { mutableStateOf(false) } 561 | val recompose = currentRecomposeScope 562 | 563 | Row( 564 | modifier = Modifier 565 | .fillMaxWidth() 566 | .padding(16.dp), 567 | horizontalArrangement = Arrangement.spacedBy(16.dp), 568 | verticalAlignment = Alignment.CenterVertically 569 | ) { 570 | // OLog.i("重绘", "触发重绘") 571 | 572 | if (appInfo.value.appIcon != null) { 573 | Image( 574 | painter = rememberDrawablePainter(appInfo.value.appIcon), 575 | modifier = Modifier 576 | .size(40.dp) 577 | .align(Alignment.CenterVertically), 578 | contentDescription = null 579 | ) 580 | } 581 | // 左边显示应用名称 582 | Column(modifier = Modifier.weight(0.5f)) { 583 | Text( 584 | text = appInfo.value.appName, 585 | style = MaterialTheme.typography.bodyMedium, 586 | color = if (!appInfo.value.isExist) Color(0xFFFF6E40) else LocalContentColor.current 587 | ) 588 | Text(text = appInfo.value.appPkg, style = MaterialTheme.typography.bodySmall) 589 | } 590 | 591 | // 中间显示禁用状态文本 592 | Text( 593 | text = if (!appInfo.value.isExist) "Unknown" else if (isDisabled.value) "Disable" else "Enable", 594 | color = if (!appInfo.value.isExist) Color(0xFFFF6E40) 595 | else if (isDisabled.value) Color(0xFFFF5252) 596 | else Color(0xFF59F0A6), 597 | style = MaterialTheme.typography.bodyMedium, 598 | modifier = Modifier.padding(end = 16.dp) 599 | ) 600 | // 右边是一个按钮 601 | IconButton( 602 | onClick = { 603 | SetAppDisabled( 604 | isDisabled, 605 | appInfo.value.appPkg, 606 | appInfo.value.isExist, 607 | true, 608 | appInfo 609 | ) 610 | } 611 | ) { 612 | 613 | val icon: ImageVector = if (appInfo.value.isExist && isDisabled.value) { 614 | Icons.Default.Check 615 | } else if (appInfo.value.isExist) { 616 | Icons.Default.Close 617 | } else { 618 | Icons.Default.Warning 619 | } 620 | Icon( 621 | imageVector = icon, 622 | 623 | contentDescription = if (!appInfo.value.isExist) "Unknown" else if (isDisabled.value) "Disable" else "Enable" 624 | ) 625 | } 626 | IconButton( 627 | onClick = { isMenuVisible = true } 628 | ) { 629 | 630 | Icon( 631 | imageVector = Icons.Default.MoreVert, 632 | contentDescription = "More" 633 | ) 634 | DropdownMenu( 635 | expanded = isMenuVisible, 636 | onDismissRequest = { isMenuVisible = false }, 637 | modifier = Modifier.background(MaterialTheme.colorScheme.surface) 638 | ) { 639 | DropdownMenuItem( 640 | leadingIcon = { 641 | Icon( 642 | imageVector = Icons.Default.Delete, 643 | contentDescription = "uninstall" 644 | ) 645 | }, 646 | text = { Text(text = "尝试卸载") }, 647 | onClick = { 648 | isMenuVisible = false;uninstall( 649 | appInfo.value, 650 | recompose 651 | ) 652 | } 653 | // 处理菜单项点击事件,这里可以添加卸载逻辑 654 | ) 655 | DropdownMenuItem( 656 | leadingIcon = { 657 | Icon( 658 | imageVector = Icons.Default.Refresh, 659 | contentDescription = "uninstall" 660 | ) 661 | }, text = { Text(text = "尝试重装") }, onClick = { 662 | // ... 663 | isMenuVisible = false 664 | reinstall(appInfo.value, recompose) 665 | }) 666 | } 667 | } 668 | 669 | } 670 | 671 | } 672 | 673 | 674 | @Composable 675 | fun AppList(appList: List) { 676 | LazyColumn( 677 | verticalArrangement = Arrangement.spacedBy(8.dp), 678 | modifier = Modifier.fillMaxSize() 679 | ) { 680 | items(optlist + appList) { appInfo -> 681 | AppListItem(appInfo) 682 | } 683 | } 684 | 685 | } 686 | 687 | private fun copyText(text: String) = getSystemService() 688 | ?.setPrimaryClip(ClipData.newPlainText(getString(R.string.app_name), text)) 689 | 690 | private suspend fun onTerminalResult(exitValue: Int, msg: String?) = 691 | withContext(Dispatchers.Main) { 692 | if (exitValue == 0 && msg.isNullOrBlank()) return@withContext 693 | MaterialAlertDialogBuilder(context).apply { 694 | if (!msg.isNullOrBlank()) { 695 | if (exitValue != 0) { 696 | setTitle(getString(R.string.operation_failed, exitValue.toString())) 697 | } else { 698 | setTitle("结果") 699 | } 700 | setMessage(msg) 701 | setNeutralButton(android.R.string.copy) { _, _ -> copyText(msg) } 702 | } else if (exitValue != 0) { 703 | setMessage(getString(R.string.operation_failed, exitValue.toString())) 704 | } 705 | }.setPositiveButton(android.R.string.ok, null).show() 706 | .findViewById(android.R.id.message) 707 | ?.setTextIsSelectable(true) 708 | } 709 | 710 | @OptIn(ExperimentalMaterial3Api::class) 711 | @Composable 712 | fun Details() { 713 | generateAppList(context) 714 | 715 | Column { 716 | //val appList = remember { generateAppList(context) } 717 | // TopAppBar 718 | TopAppBar(title = { Text(text = "XHyper") }, 719 | actions = { 720 | IconButton(onClick = { 721 | val inputEditText = EditText(context) 722 | inputEditText.hint = "Terminal" 723 | inputEditText.inputType = InputType.TYPE_CLASS_TEXT 724 | 725 | MaterialAlertDialogBuilder(context) 726 | .setTitle("终端") 727 | .setView(inputEditText) 728 | .setPositiveButton(android.R.string.ok) { _, _ -> 729 | lifecycleScope.launch { 730 | val result = 731 | ShizukuExec(inputEditText.text.toString().toByteArray()) 732 | OLog.i("终端结果:", result!!) 733 | onTerminalResult(ReturnValue, result) 734 | } 735 | } 736 | .setNegativeButton(android.R.string.cancel, null) 737 | .show() 738 | 739 | }) { 740 | Icon( 741 | imageVector = ImageVector.Companion.vectorResource(R.drawable.ic_baseline_terminal), 742 | contentDescription = "terminal" 743 | ) 744 | } 745 | IconButton( 746 | onClick = { 747 | val options = arrayOf( 748 | "pm命令", 749 | "pm命令(增强)", 750 | "service call(Android 12)", 751 | "service call(Android 13)" 752 | ) 753 | var selectedItem = SpUtils.getParam(context, "method", 1) as Int 754 | Toast.makeText( 755 | context, 756 | "设置卸载、重装操作的实现方案\nservice call一般可以卸载更多app", 757 | Toast.LENGTH_SHORT 758 | ).show() 759 | MaterialAlertDialogBuilder(context) 760 | .setTitle("设置方案") 761 | .setSingleChoiceItems(options, selectedItem) { _, which -> 762 | // 设置选中状态 763 | selectedItem = which 764 | } 765 | .setPositiveButton("确定") { _, _ -> 766 | // 处理确定按钮点击事件,可以根据 selectedItem 执行相应逻辑 767 | if (selectedItem != -1) { 768 | when (selectedItem) { 769 | 0 -> { 770 | // 选择了 "pm命令" 771 | SpUtils.setParam(context, "method", 0) 772 | } 773 | 774 | 1 -> { 775 | // 选择了 "pm命令" 776 | SpUtils.setParam(context, "method", 1) 777 | } 778 | 779 | 2 -> { 780 | // 选择了 "service call(Android 12)" 781 | SpUtils.setParam(context, "method", 2) 782 | } 783 | 784 | 3 -> { 785 | // 选择了 "service call(Android 13)" 786 | SpUtils.setParam(context, "method", 3) 787 | } 788 | } 789 | } 790 | } 791 | .setNegativeButton("取消") { dialog, _ -> 792 | // 处理取消按钮点击事件 793 | dialog.dismiss() 794 | } 795 | .show() 796 | } 797 | ) { 798 | Icon( 799 | imageVector = Icons.Outlined.Settings, 800 | contentDescription = "settings" 801 | ) 802 | } 803 | }) 804 | // AppList 805 | AppList(appList = pkglist) 806 | } 807 | } 808 | 809 | @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") 810 | @OptIn(ExperimentalMaterial3Api::class) 811 | @Composable 812 | fun AppListScreen(context: Context) { 813 | val navController = rememberNavController() 814 | Scaffold( 815 | //设置底部导航栏 816 | bottomBar = { 817 | NavigationBar { 818 | val navBackStackEntry by navController.currentBackStackEntryAsState() 819 | val currentDestination = navBackStackEntry?.destination 820 | NavigationBarItem( 821 | 822 | icon = { 823 | when (currentDestination?.route) { 824 | "1" -> { 825 | // 选中时的图标 826 | Icon(Icons.Filled.Settings, contentDescription = null) 827 | } 828 | 829 | else -> { 830 | // 未选中时的图标 831 | Icon(Icons.Outlined.Settings, contentDescription = null) 832 | } 833 | } 834 | }, 835 | label = { 836 | Text( 837 | text = "Optimization" 838 | // modifier = Modifier.alpha(if (currentDestination?.route == "Details") 1f else 0f) 839 | ) 840 | }, 841 | selected = currentDestination?.route == "1", 842 | alwaysShowLabel = false, 843 | onClick = { 844 | navController.navigate("1") { 845 | popUpTo(navController.graph.startDestinationId) { 846 | saveState = true 847 | } 848 | launchSingleTop = true 849 | restoreState = true 850 | } 851 | } 852 | ) 853 | NavigationBarItem( 854 | icon = { 855 | when (currentDestination?.route) { 856 | "2" -> { 857 | // 选中时的图标 858 | Icon(Icons.Filled.Create, contentDescription = null) 859 | } 860 | 861 | else -> { 862 | // 未选中时的图标 863 | Icon(Icons.Outlined.Create, contentDescription = null) 864 | } 865 | } 866 | }, 867 | label = { 868 | Text( 869 | text = "Details", 870 | // modifier = Modifier.alpha(if (currentDestination?.route == "Details") 1f else 0f) 871 | ) 872 | }, 873 | selected = currentDestination?.route == "2", 874 | alwaysShowLabel = false, 875 | onClick = { 876 | navController.navigate("2") { 877 | popUpTo(navController.graph.startDestinationId) { 878 | saveState = true 879 | } 880 | launchSingleTop = true 881 | restoreState = true 882 | } 883 | } 884 | ) 885 | NavigationBarItem( 886 | icon = { 887 | when (currentDestination?.route) { 888 | "3" -> { 889 | // 选中时的图标 890 | Icon(Icons.Filled.Info, contentDescription = null) 891 | } 892 | 893 | else -> { 894 | // 未选中时的图标 895 | Icon(Icons.Outlined.Info, contentDescription = null) 896 | } 897 | } 898 | }, 899 | label = { 900 | Text( 901 | text = "About", 902 | // modifier = Modifier.alpha(if (currentDestination?.route == "About") 1f else 0f) 903 | ) 904 | }, 905 | selected = currentDestination?.route == "3", 906 | alwaysShowLabel = false, 907 | onClick = { 908 | navController.navigate("3") { 909 | popUpTo(navController.graph.startDestinationId) { 910 | saveState = true 911 | } 912 | launchSingleTop = true 913 | restoreState = true 914 | } 915 | } 916 | ) 917 | } 918 | 919 | 920 | } 921 | 922 | ) { 923 | Column( 924 | modifier = Modifier 925 | .fillMaxSize() 926 | .padding(bottom = it.calculateBottomPadding()) // 添加 padding,防止遮挡内容 927 | ) { 928 | NavHost( 929 | navController = navController, 930 | startDestination = "1" 931 | ) { 932 | OLog.i("界面", "绘制横屏开始") 933 | composable("2") { Details() } 934 | composable("3") { AboutPage() } 935 | composable("1") { OptPage() } 936 | // 添加其他页面的 composable 函数,类似上面的示例 937 | } 938 | } 939 | } 940 | 941 | } 942 | 943 | 944 | @Composable 945 | fun AppListContent() { 946 | AppListScreen(LocalContext.current) 947 | } 948 | 949 | fun generateAppList(context: Context): List { 950 | var a: Boolean 951 | // 这里添加你的应用信息 952 | for (appinfo in pkglist) { 953 | if (OPackage.isInstalled(appinfo.appPkg, context.packageManager)) { 954 | appinfo.appName = getAppNameByPackageName(context, appinfo.appPkg) 955 | a = isAppDisabled(appinfo.appPkg) 956 | appinfo.isDisabled = a 957 | } else { 958 | appinfo.isExist = false 959 | appinfo.appName = "未安装" 960 | } 961 | appinfo.appIcon = getAppIconByPackageName(appinfo.appPkg, context.packageManager) 962 | } 963 | for (appinfo in optlist) { 964 | if (OPackage.isInstalled(appinfo.appPkg, context.packageManager)) { 965 | appinfo.appName = getAppNameByPackageName(context, appinfo.appPkg) 966 | a = isAppDisabled(appinfo.appPkg) 967 | appinfo.isDisabled = a 968 | } else { 969 | appinfo.isExist = false 970 | appinfo.appName = "未安装" 971 | } 972 | appinfo.appIcon = getAppIconByPackageName(appinfo.appPkg, context.packageManager) 973 | } 974 | OLog.i("列表项", pkglist.toString()) 975 | return pkglist 976 | } 977 | 978 | @Preview(showBackground = true) 979 | @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) 980 | @Composable 981 | fun GreetingPreview() { 982 | OriginPlanTheme { 983 | // A surface container using the 'background' color from the theme 984 | Surface( 985 | modifier = Modifier.fillMaxSize(), 986 | color = MaterialTheme.colorScheme.background 987 | ) { 988 | OptPage() 989 | } 990 | } 991 | } 992 | 993 | companion object { 994 | @SuppressLint("StaticFieldLeak") 995 | lateinit var app: XPlanForHyper private set 996 | } 997 | } 998 | 999 | 1000 | 1001 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/datatype/AppInfo.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.datatype 2 | 3 | import android.graphics.drawable.Drawable 4 | 5 | data class AppInfo( 6 | var appName: String, 7 | val appPkg: String, 8 | var appIcon: Drawable?=null, 9 | var isDisabled: Boolean = false, 10 | var isExist: Boolean = true 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/datatype/ConfigData.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.datatype 2 | 3 | private val dataList: List> = emptyList() 4 | 5 | data class ConfigData( 6 | var data: List> = dataList, 7 | var shell: String = "", 8 | var restore :String="", 9 | var debug: String = "" 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/datatype/OriginCardItem.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.datatype 2 | 3 | import androidx.compose.ui.graphics.vector.ImageVector 4 | 5 | data class OriginCardItem( 6 | val icon: ImageVector? = null, 7 | val label: String, 8 | val content: String? = null, 9 | val onClick: (() -> Unit)? = null 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/AboutPage.kt: -------------------------------------------------------------------------------- 1 | import android.content.Context 2 | import androidx.compose.foundation.layout.Arrangement 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.layout.windowInsetsPadding 7 | import androidx.compose.foundation.lazy.LazyColumn 8 | import androidx.compose.material3.ExperimentalMaterial3Api 9 | import androidx.compose.material3.Scaffold 10 | import androidx.compose.material3.Text 11 | import androidx.compose.material3.TopAppBar 12 | import androidx.compose.material3.TopAppBarDefaults 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.unit.dp 16 | 17 | @OptIn(ExperimentalMaterial3Api::class) 18 | @Composable 19 | fun AboutPage() { 20 | Scaffold( 21 | modifier = Modifier 22 | .windowInsetsPadding(TopAppBarDefaults.windowInsets) 23 | .fillMaxSize(), 24 | topBar = { 25 | TopAppBar( 26 | title = { 27 | Text(text = "关于") 28 | }, 29 | ) 30 | }, 31 | ) { 32 | LazyColumn( 33 | contentPadding = PaddingValues(16.dp), 34 | modifier = Modifier 35 | .fillMaxSize() 36 | .padding(it), 37 | verticalArrangement = Arrangement.spacedBy(16.dp), 38 | ) { 39 | item { 40 | StatusWidget() 41 | } 42 | item { 43 | DonateWidget() 44 | } 45 | item { 46 | DiscussWidget() 47 | } 48 | item { 49 | OpenSourceWidget() 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/OptPage.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.res.Configuration 6 | import androidx.compose.foundation.layout.Arrangement 7 | import androidx.compose.foundation.layout.Column 8 | import androidx.compose.foundation.layout.Row 9 | import androidx.compose.foundation.layout.fillMaxSize 10 | import androidx.compose.foundation.layout.fillMaxWidth 11 | import androidx.compose.foundation.layout.statusBarsPadding 12 | import androidx.compose.foundation.rememberScrollState 13 | import androidx.compose.material.icons.Icons 14 | import androidx.compose.material.icons.outlined.Notifications 15 | import androidx.compose.material3.ExperimentalMaterial3Api 16 | import androidx.compose.material3.Icon 17 | import androidx.compose.material3.IconButton 18 | import androidx.compose.material3.MaterialTheme 19 | import androidx.compose.material3.Scaffold 20 | import androidx.compose.material3.Surface 21 | import androidx.compose.material3.Text 22 | import androidx.compose.material3.TopAppBar 23 | import androidx.compose.runtime.Composable 24 | import androidx.compose.ui.Alignment 25 | import androidx.compose.ui.Modifier 26 | import androidx.compose.ui.tooling.preview.Preview 27 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 28 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 29 | import com.itos.xplanforhyper.ui.Pages.subassemblies.Opt.ControlSystemUpdateButton 30 | import com.itos.xplanforhyper.ui.Pages.subassemblies.Opt.HDButton 31 | import com.itos.xplanforhyper.ui.Pages.subassemblies.Opt.OptButton 32 | import com.itos.xplanforhyper.ui.Pages.subassemblies.Opt.ProcessLimitButton 33 | import com.itos.xplanforhyper.ui.theme.OriginPlanTheme 34 | import com.itos.xplanforhyper.utils.OData 35 | 36 | 37 | fun SettingsDebug() { 38 | MaterialAlertDialogBuilder(app) 39 | .setTitle("调试") 40 | .setMessage("这是调试功能,您确定要使用吗?") 41 | .setPositiveButton("OK") { _, _ -> 42 | val temp = app.ShizukuExec(OData.configdata.debug.toByteArray()) 43 | MaterialAlertDialogBuilder(app) 44 | .setTitle("调试信息") 45 | .setMessage(temp) 46 | .setPositiveButton("OK", null) 47 | .show() 48 | } 49 | .show() 50 | } 51 | 52 | @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") 53 | @OptIn(ExperimentalMaterial3Api::class) 54 | @Composable 55 | fun OptPage() { 56 | Scaffold(modifier = Modifier 57 | .fillMaxSize() 58 | .statusBarsPadding(), 59 | topBar = { 60 | TopAppBar( 61 | title = { 62 | Text(text = "优化") 63 | }, 64 | actions = { 65 | // IconButton( 66 | // onClick = { 67 | //// SettingsDebug() 68 | // 69 | // } 70 | // ) { 71 | // Icon( 72 | // imageVector = Icons.Outlined.Build, 73 | // contentDescription = "Debug" 74 | // ) 75 | // } 76 | IconButton( 77 | onClick = { 78 | MaterialAlertDialogBuilder(app) 79 | .setTitle("公告") 80 | .setMessage(app.show_notice) 81 | .setPositiveButton("了解") { dialog, which -> 82 | dialog.dismiss() 83 | } 84 | .show() 85 | } 86 | ) { 87 | Icon( 88 | imageVector = Icons.Outlined.Notifications, 89 | contentDescription = "help" 90 | ) 91 | } 92 | } 93 | ) 94 | }) { 95 | if (isLandscape(app)) { 96 | 97 | val scrollState = rememberScrollState() 98 | // 执行横屏时的操作 99 | Column( 100 | modifier = Modifier 101 | .fillMaxSize(), 102 | // .verticalScroll(scrollState) 103 | // .padding(top = getStatusBarHeight().dp), 104 | horizontalAlignment = Alignment.CenterHorizontally, 105 | verticalArrangement = Arrangement.Center // 将子项垂直居中 106 | ) { 107 | Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) { 108 | OptButton() 109 | ProcessLimitButton() 110 | } 111 | 112 | Row (modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly){ 113 | HDButton() 114 | ControlSystemUpdateButton() 115 | } 116 | // Settings_opt() 117 | 118 | } 119 | } else { 120 | // 执行竖屏时的操作 121 | Column( 122 | modifier = Modifier 123 | .fillMaxSize() 124 | .statusBarsPadding(), 125 | horizontalAlignment = Alignment.CenterHorizontally, 126 | verticalArrangement = Arrangement.Center // 将子项垂直居中 127 | ) { 128 | OptButton() 129 | ProcessLimitButton() 130 | // Settings_opt() 131 | HDButton() 132 | ControlSystemUpdateButton() 133 | } 134 | } 135 | 136 | } 137 | } 138 | 139 | fun isLandscape(context: Context): Boolean { 140 | val configuration = context.resources.configuration 141 | return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE 142 | } 143 | 144 | fun getStatusBarHeight(): Int { 145 | var result = 0 146 | val resourceId: Int = app.resources.getIdentifier("status_bar_height", "dimen", "android") 147 | if (resourceId > 0) { 148 | result = app.resources.getDimensionPixelSize(resourceId) 149 | } 150 | 151 | return result 152 | } 153 | 154 | @OptIn(ExperimentalMaterial3Api::class) 155 | @Preview(showBackground = true) 156 | @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) 157 | @Composable 158 | fun a() { 159 | OriginPlanTheme { 160 | // A surface container using the 'background' color from the theme 161 | Surface( 162 | modifier = Modifier.fillMaxSize(), 163 | color = MaterialTheme.colorScheme.background 164 | ) { 165 | OptPage() 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/About/DiscussWidget.kt: -------------------------------------------------------------------------------- 1 | 2 | import android.content.Intent 3 | import android.net.Uri 4 | import android.text.util.Linkify 5 | import android.widget.Toast 6 | import androidx.compose.material3.Text 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.graphics.vector.ImageVector 9 | import androidx.compose.ui.res.vectorResource 10 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 11 | import com.google.android.material.textview.MaterialTextView 12 | import com.itos.xplanforhyper.R 13 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 14 | import com.itos.xplanforhyper.datatype.OriginCardItem 15 | import com.itos.xplanforhyper.utils.OUI 16 | 17 | fun show_author() { 18 | try { 19 | val intent = Intent(Intent.ACTION_VIEW) 20 | intent.data = Uri.parse("coolmarket://u/3287595") 21 | app.startActivity(intent) 22 | app.finish() 23 | } catch (e: java.lang.Exception) { 24 | Toast.makeText(app, "打开酷安失败,已为您打开作者B站", Toast.LENGTH_SHORT).show() 25 | OUI.openLink("https://space.bilibili.com/329223542") 26 | } 27 | } 28 | 29 | fun moreapp() { 30 | MaterialAlertDialogBuilder(app) 31 | .setTitle("更多软件") 32 | .setMessage(app.resources.openRawResource(R.raw.moreapp).bufferedReader().readText()) 33 | .setPositiveButton("了解", null) 34 | .show() 35 | .findViewById(android.R.id.message)?.apply { 36 | setTextIsSelectable(true) 37 | Linkify.addLinks(this, Linkify.EMAIL_ADDRESSES or Linkify.WEB_URLS) 38 | // The first time the link is clicked the background does not change color and 39 | // the view needs to get focus once. 40 | requestFocus() 41 | } 42 | 43 | } 44 | @Composable 45 | fun DiscussWidget() { 46 | val items = listOf( 47 | OriginCardItem( 48 | icon = ImageVector.vectorResource(R.drawable.ic_bilibili), 49 | label = "BiliBili(开发者)", 50 | onClick = { 51 | OUI.openLink("https://space.bilibili.com/329223542") 52 | }), 53 | OriginCardItem( 54 | icon = ImageVector.vectorResource(R.drawable.ic_bilibili), 55 | label = "BiliBili(合作伙伴)", 56 | onClick = { 57 | OUI.openLink("https://space.bilibili.com/1289434708") 58 | } 59 | ), 60 | OriginCardItem( 61 | icon = ImageVector.vectorResource(R.drawable.ic_outline_coolapk), 62 | label = "酷安(开发者)", 63 | onClick = { 64 | show_author() 65 | } 66 | ), 67 | OriginCardItem( 68 | icon = ImageVector.vectorResource(R.drawable.ic_outline_qq), 69 | label = "QQ频道", 70 | onClick = { 71 | OUI.openLink("https://pd.qq.com/s/8vadinclc") 72 | } 73 | ), 74 | // OriginCardItem( 75 | // icon = Icons.Default.Share, 76 | // label = "更多软件", 77 | // onClick = { 78 | // moreapp() 79 | // } 80 | // ), 81 | ) 82 | ItemsCardWidget( 83 | title = { 84 | Text(text = "讨论&反馈&联系我们") 85 | }, 86 | items = items, 87 | showItemIcon = true 88 | ) 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/About/DonateWidget.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.material3.Text 2 | import androidx.compose.runtime.Composable 3 | import androidx.compose.ui.graphics.vector.ImageVector 4 | import androidx.compose.ui.platform.LocalContext 5 | import androidx.compose.ui.res.vectorResource 6 | import com.itos.xplanforhyper.R 7 | import com.itos.xplanforhyper.datatype.OriginCardItem 8 | import com.itos.xplanforhyper.utils.OUI 9 | 10 | @Composable 11 | fun DonateWidget() { 12 | LocalContext.current 13 | 14 | val items = listOf( 15 | OriginCardItem( 16 | icon = ImageVector.vectorResource(R.drawable.ic_alipay), 17 | label = "支付宝", 18 | onClick = { 19 | OUI.showImageDialog("zfb.jpg") 20 | } 21 | ), 22 | OriginCardItem( 23 | icon = ImageVector.vectorResource(R.drawable.ic_wechatpay), 24 | label = "微信", 25 | onClick = { 26 | OUI.showImageDialog("wx.png") 27 | } 28 | ), 29 | 30 | ) 31 | ItemsCardWidget( 32 | title = { 33 | Text(text = "捐赠") 34 | }, 35 | items = items, 36 | showItemIcon = true 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/About/OpenSourceWidget.kt: -------------------------------------------------------------------------------- 1 | 2 | import android.text.util.Linkify 3 | import androidx.compose.material3.Text 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.graphics.vector.ImageVector 6 | import androidx.compose.ui.res.vectorResource 7 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 8 | import com.google.android.material.textview.MaterialTextView 9 | import com.itos.xplanforhyper.R 10 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 11 | import com.itos.xplanforhyper.datatype.OriginCardItem 12 | import com.itos.xplanforhyper.utils.OUI 13 | 14 | fun showLicenses() { 15 | MaterialAlertDialogBuilder(app) 16 | .setTitle(R.string.action_licenses) 17 | .setMessage( 18 | app.resources.openRawResource(R.raw.licenses).bufferedReader().readText() 19 | ) 20 | .setPositiveButton(android.R.string.ok, null) 21 | .show() 22 | .findViewById(android.R.id.message)?.apply { 23 | setTextIsSelectable(true) 24 | Linkify.addLinks(this, Linkify.EMAIL_ADDRESSES or Linkify.WEB_URLS) 25 | requestFocus() 26 | } 27 | } 28 | 29 | @Composable 30 | fun OpenSourceWidget() { 31 | val items = listOf( 32 | OriginCardItem( 33 | icon = ImageVector.vectorResource(R.drawable.ic_outline_code), 34 | 35 | label = "Github", 36 | onClick = { 37 | OUI.openLink("https://github.com/ItosEO/XPlanForHyper") 38 | } 39 | ), 40 | OriginCardItem( 41 | icon = ImageVector.vectorResource(R.drawable.ic_outline_lisence), 42 | 43 | label = "许可证", 44 | onClick = { 45 | showLicenses() 46 | } 47 | ), 48 | 49 | ) 50 | ItemsCardWidget( 51 | title = { 52 | Text(text = "开源") 53 | }, 54 | items = items, 55 | showItemIcon = true 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/About/StatusWidget.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.foundation.Image 2 | import androidx.compose.foundation.layout.Box 3 | import androidx.compose.foundation.layout.fillMaxWidth 4 | import androidx.compose.foundation.layout.size 5 | import androidx.compose.material3.CardDefaults 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.Text 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Alignment 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.platform.LocalContext 12 | import androidx.compose.ui.res.stringResource 13 | import androidx.compose.ui.unit.dp 14 | import androidx.core.content.ContextCompat 15 | import com.google.accompanist.drawablepainter.rememberDrawablePainter 16 | import com.itos.xplanforhyper.BuildConfig 17 | import com.itos.xplanforhyper.R 18 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 19 | 20 | @Composable 21 | fun StatusWidget() { 22 | val containerColor = MaterialTheme.colorScheme.primaryContainer 23 | val onContainerColor = MaterialTheme.colorScheme.onPrimaryContainer 24 | 25 | val level = app.getString(R.string.build_type) 26 | 27 | CardWidget( 28 | colors = CardDefaults.elevatedCardColors( 29 | containerColor = containerColor, 30 | contentColor = onContainerColor 31 | ), 32 | icon = { 33 | Image( 34 | modifier = Modifier 35 | .size(56.dp), 36 | painter = rememberDrawablePainter( 37 | drawable = ContextCompat.getDrawable( 38 | LocalContext.current, 39 | R.mipmap.ic_launcher_xplan 40 | ) 41 | ), 42 | contentDescription = stringResource(id = R.string.app_name) 43 | ) 44 | }, 45 | title = { 46 | Text( 47 | modifier = Modifier, 48 | text = stringResource(id = R.string.app_name), 49 | style = MaterialTheme.typography.titleMedium, 50 | ) 51 | }, 52 | content = { 53 | Box(modifier = Modifier.fillMaxWidth()) { 54 | Text( 55 | modifier = Modifier.align(Alignment.Center), 56 | text = "$level [${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})]", 57 | style = MaterialTheme.typography.bodyMedium, 58 | ) 59 | } 60 | } 61 | ) 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/Opt/ControlSystemUpdateButton.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.Pages.subassemblies.Opt 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.foundation.layout.Spacer 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.layout.size 7 | import androidx.compose.foundation.layout.width 8 | import androidx.compose.foundation.shape.RoundedCornerShape 9 | import androidx.compose.material3.FilledTonalButton 10 | import androidx.compose.material3.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.text.style.TextAlign 14 | import androidx.compose.ui.unit.dp 15 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 16 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 17 | import com.itos.xplanforhyper.utils.OShizuku 18 | import com.itos.xplanforhyper.utils.SpUtils 19 | 20 | @Composable 21 | fun ControlSystemUpdateButton(){ 22 | Row( 23 | modifier = Modifier 24 | .padding(vertical = 45.dp) 25 | ) { 26 | FilledTonalButton( 27 | modifier = Modifier 28 | .size(width = 130.dp, height = 70.dp), 29 | shape = RoundedCornerShape(30), 30 | onClick = { DisableSystemUpdate() } 31 | ) { 32 | Text("禁用\n系统更新", textAlign = TextAlign.Center) 33 | } 34 | Spacer(modifier = Modifier.width(25.dp)) 35 | FilledTonalButton( 36 | modifier = Modifier 37 | .size(width = 130.dp, height = 70.dp), 38 | shape = RoundedCornerShape(30), 39 | onClick = { EnableSystemUpdate() } 40 | ) { 41 | Text("恢复\n系统更新", textAlign = TextAlign.Center) 42 | } 43 | } 44 | } 45 | 46 | private fun DisableSystemUpdate(){ 47 | if (app.b && app.c) { 48 | // val isExist=OPackage.isInstalled("com.android.updater",XPlanForHyper.app.packageManager) 49 | // XPlanForHyper.app.SetAppDisabled(mutableStateOf(true), "com.android.updater", isExist, false) 50 | MaterialAlertDialogBuilder(app) 51 | .setTitle("禁用系统更新") 52 | .setMessage("该操作可能导致卡米,您确定要进行吗?") 53 | .setPositiveButton("确定") { _, _ -> 54 | uninstall("com.android.updater") 55 | MaterialAlertDialogBuilder(app) 56 | .setTitle("完成") 57 | .setMessage("禁用系统更新完成") 58 | .setPositiveButton(android.R.string.ok, null) 59 | .show() 60 | app.generateAppList(app) 61 | } 62 | .setNegativeButton("取消",null) 63 | .show() 64 | } else { 65 | OShizuku.checkShizuku() 66 | } 67 | } 68 | 69 | private fun EnableSystemUpdate(){ 70 | if (app.b && app.c) { 71 | // val isExist=OPackage.isInstalled("com.android.updater", app.packageManager) 72 | // app.SetAppDisabled(mutableStateOf(false), "com.android.updater", isExist, false) 73 | reinstall("com.android.updater") 74 | MaterialAlertDialogBuilder(app) 75 | .setTitle("完成") 76 | .setMessage("已恢复系统更新") 77 | .setPositiveButton(android.R.string.ok, null) 78 | .show() 79 | app.generateAppList(app) 80 | } else { 81 | OShizuku.checkShizuku() 82 | } 83 | } 84 | 85 | private fun uninstall(packagename: String) { 86 | when (SpUtils.getParam(app.context, "method", 1)) { 87 | 3 -> { 88 | app.ShizukuExec("service call package 131 s16 $packagename i32 0 i32 0".toByteArray()) 89 | } 90 | 91 | 2 -> { 92 | app.ShizukuExec("service call package 134 s16 $packagename i32 0 i32 0".toByteArray()) 93 | } 94 | 95 | 1 -> { 96 | app.ShizukuExec("pm uninstall --user 0 $packagename".toByteArray()) 97 | } 98 | else -> { 99 | app.ShizukuExec("pm uninstall $packagename".toByteArray()) 100 | } 101 | 102 | } 103 | } 104 | 105 | private fun reinstall(packagename: String) { 106 | when (SpUtils.getParam(app, "method", 1)) { 107 | 3 -> { 108 | app.ShizukuExec("service call package 131 s16 $packagename i32 1 i32 0".toByteArray()) 109 | } 110 | 111 | 2 -> { 112 | app.ShizukuExec("service call package 134 s16 $packagename i32 1 i32 0".toByteArray()) 113 | } 114 | 115 | else -> { 116 | app.ShizukuExec("pm install-existing $packagename".toByteArray()) 117 | } 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/Opt/HDButton.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.Pages.subassemblies.Opt 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.foundation.layout.Spacer 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.layout.size 7 | import androidx.compose.foundation.layout.width 8 | import androidx.compose.foundation.shape.RoundedCornerShape 9 | import androidx.compose.material3.FilledTonalButton 10 | import androidx.compose.material3.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.unit.dp 14 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 15 | import com.itos.xplanforhyper.utils.OLog 16 | 17 | @Composable 18 | fun HDButton() { 19 | Row( 20 | modifier = Modifier 21 | .padding(vertical = 45.dp) 22 | ) { 23 | FilledTonalButton( 24 | modifier = Modifier 25 | .size(width = 130.dp, height = 70.dp), 26 | shape = RoundedCornerShape(30), 27 | onClick = { HideHD() } 28 | ) { 29 | Text("隐藏HD") 30 | } 31 | Spacer(modifier = Modifier.width(25.dp)) 32 | FilledTonalButton( 33 | modifier = Modifier 34 | .size(width = 130.dp, height = 70.dp), 35 | shape = RoundedCornerShape(30), 36 | onClick = { UnHideHD() } 37 | ) { 38 | Text("还原HD") 39 | } 40 | } 41 | } 42 | 43 | fun HideHD() { 44 | OLog.i("隐藏HD", "Shizuku方案") 45 | 46 | var data = app.ShizukuExec("settings get secure icon_blacklist".toByteArray()) 47 | OLog.i("隐藏HD", "当前黑名单列表: $data") 48 | data = data!!.trimEnd() 49 | data = data.replace(Regex(",+"), ",") 50 | data = data.replace(Regex("(,rotate,hd)+"), ",rotate,hd") 51 | data = "$data,rotate,hd" 52 | OLog.i("隐藏HD", "处理后黑名单列表: $data") 53 | app.ShizukuExec("settings put secure icon_blacklist $data,rotate,hd".toByteArray()) 54 | // if (OData.is_have_premissipn) { 55 | // OLog.i("隐藏HD", "Java方案") 56 | // 57 | // var data = Settings.Secure.getString(app.contentResolver, "icon_blacklist") 58 | // OLog.i("隐藏HD", "当前黑名单列表: $data") 59 | // data = data!!.trimEnd() 60 | // data = data.replace(Regex(",+"), ",") 61 | // data = "$data,rotate,hd" 62 | // data = data.replace(Regex("(,rotate,hd)+"), ",rotate,hd") 63 | // OLog.i("隐藏HD", "处理后黑名单列表: $data") 64 | // Settings.Secure.putString(app.contentResolver, "icon_blacklist", data) 65 | // } else { 66 | // OLog.i("隐藏HD", "Shizuku方案") 67 | // 68 | // var data = app.ShizukuExec("settings get secure icon_blacklist".toByteArray()) 69 | // OLog.i("隐藏HD", "当前黑名单列表: $data") 70 | // data = data!!.trimEnd() 71 | // data = data.replace(Regex(",+"), ",") 72 | // data = data.replace(Regex("(,rotate,hd)+"), ",rotate,hd") 73 | // data = "$data,rotate,hd" 74 | // OLog.i("隐藏HD", "处理后黑名单列表: $data") 75 | // app.ShizukuExec("settings put secure icon_blacklist $data,rotate,hd".toByteArray()) 76 | // 77 | // } 78 | } 79 | 80 | fun UnHideHD() { 81 | 82 | OLog.i("还原HD", "Shizuku方案") 83 | 84 | var data = app.ShizukuExec("settings get secure icon_blacklist".toByteArray()) 85 | data = data!!.trimEnd() 86 | 87 | OLog.i("还原HD", "待处理数据: $data") 88 | val targets = listOf("hd") 89 | // 构建正则表达式,使用 joinToString 将多个子串连接起来 90 | val regex = targets.joinToString(separator = "|").toRegex() 91 | // 使用正则表达式替换为"" 92 | var resultString = regex.replace(data, "") 93 | resultString = resultString.replace(Regex("(,rotate)+"), ",rotate") 94 | resultString = resultString.replace(Regex(",+"), ",") 95 | OLog.i("还原HD", "处理结果: $resultString") 96 | 97 | app.ShizukuExec("settings put secure icon_blacklist $resultString".toByteArray())// if (OData.is_have_premissipn) { 98 | // OLog.i("还原HD", "Java方案") 99 | // 100 | // var data = Settings.Secure.getString(app.contentResolver, "icon_blacklist") 101 | // data = data!!.trimEnd() 102 | // 103 | // OLog.i("还原HD", "待处理数据: $data") 104 | // val targets = listOf("hd") 105 | // // 构建正则表达式,使用 joinToString 将多个子串连接起来 106 | // val regex = targets.joinToString(separator = "|").toRegex() 107 | // // 使用正则表达式替换为"" 108 | // var resultString = regex.replace(data, "") 109 | // resultString = resultString.replace(Regex("(,rotate)+"), ",rotate") 110 | // resultString = resultString.replace(Regex(",+"), ",") 111 | // OLog.i("还原HD", "处理结果: $resultString") 112 | // 113 | // Settings.Secure.putString(app.contentResolver, "icon_blacklist", resultString) 114 | // } else { 115 | // OLog.i("还原HD", "Shizuku方案") 116 | // 117 | // var data = app.ShizukuExec("settings get secure icon_blacklist".toByteArray()) 118 | // data = data!!.trimEnd() 119 | // 120 | // OLog.i("还原HD", "待处理数据: $data") 121 | // val targets = listOf("hd") 122 | // // 构建正则表达式,使用 joinToString 将多个子串连接起来 123 | // val regex = targets.joinToString(separator = "|").toRegex() 124 | // // 使用正则表达式替换为"" 125 | // var resultString = regex.replace(data, "") 126 | // resultString = resultString.replace(Regex("(,rotate)+"), ",rotate") 127 | // resultString = resultString.replace(Regex(",+"), ",") 128 | // OLog.i("还原HD", "处理结果: $resultString") 129 | // 130 | // app.ShizukuExec("settings put secure icon_blacklist $resultString".toByteArray()) 131 | // } 132 | } 133 | 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/Opt/OptButton.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.Pages.subassemblies.Opt 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.foundation.layout.Spacer 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.layout.size 7 | import androidx.compose.foundation.layout.width 8 | import androidx.compose.foundation.shape.RoundedCornerShape 9 | import androidx.compose.material3.FilledTonalButton 10 | import androidx.compose.material3.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.mutableStateOf 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.unit.dp 15 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 16 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 17 | import com.itos.xplanforhyper.utils.OShizuku 18 | 19 | @Composable 20 | fun OptButton(){ 21 | Row( 22 | modifier = Modifier 23 | .padding(vertical = 45.dp) 24 | ) { 25 | FilledTonalButton( 26 | modifier = Modifier 27 | .size(width = 130.dp, height = 70.dp), 28 | shape = RoundedCornerShape(30), 29 | onClick = { opt_setappstauts(false) } 30 | ) { 31 | Text("一键优化") 32 | } 33 | Spacer(modifier = Modifier.width(25.dp)) 34 | FilledTonalButton( 35 | modifier = Modifier 36 | .size(width = 130.dp, height = 70.dp), 37 | shape = RoundedCornerShape(30), 38 | onClick = { opt_setappstauts(true) } 39 | ) { 40 | Text("还原") 41 | } 42 | } 43 | } 44 | 45 | fun opt_setappstauts(status: Boolean) { 46 | if (app.b && app.c) { 47 | app.generateAppList(app) 48 | // 遍历app list 49 | for (appInfo in app.optlist) { 50 | if (appInfo.isExist) { 51 | app.SetAppDisabled(mutableStateOf(status), appInfo.appPkg, appInfo.isExist, false) 52 | appInfo.isDisabled = app.isAppDisabled(appInfo.appPkg) 53 | } 54 | } 55 | if (!status) { 56 | MaterialAlertDialogBuilder(app) 57 | .setTitle("完成") 58 | .setMessage("一键优化完成") 59 | .setPositiveButton(android.R.string.ok, null) 60 | .show() 61 | } else { 62 | MaterialAlertDialogBuilder(app) 63 | .setTitle("完成") 64 | .setMessage("还原完成") 65 | .setPositiveButton(android.R.string.ok, null) 66 | .show() 67 | } 68 | app.generateAppList(app) 69 | } else { 70 | OShizuku.checkShizuku() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/Opt/ProcessLimitButton.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.Pages.subassemblies.Opt 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.compose.foundation.layout.Row 5 | import androidx.compose.foundation.layout.Spacer 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.layout.size 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.foundation.shape.RoundedCornerShape 10 | import androidx.compose.material3.FilledTonalButton 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.text.style.TextAlign 15 | import androidx.compose.ui.unit.dp 16 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 17 | 18 | @SuppressLint("StaticFieldLeak") 19 | 20 | @Composable 21 | fun ProcessLimitButton(){ 22 | Row( 23 | modifier = Modifier 24 | .padding(vertical = 45.dp) 25 | ) { 26 | FilledTonalButton( 27 | modifier = Modifier 28 | .size(width = 130.dp, height = 70.dp), 29 | shape = RoundedCornerShape(30), 30 | onClick = { 31 | app.patchProcessLimit() 32 | } 33 | ) { 34 | Text("调整后台进程设置", textAlign = TextAlign.Center) 35 | } 36 | Spacer(modifier = Modifier.width(25.dp)) 37 | FilledTonalButton( 38 | modifier = Modifier 39 | .size(width = 130.dp, height = 70.dp), 40 | shape = RoundedCornerShape(30), 41 | onClick = { 42 | app.unpatchProcessLimit() 43 | } 44 | ) { 45 | Text("还原\n进程设置", textAlign = TextAlign.Center) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/Pages/subassemblies/Opt/SettingsOptButton.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.Pages.subassemblies.Opt 2 | 3 | import android.widget.Toast 4 | import androidx.compose.foundation.layout.Row 5 | import androidx.compose.foundation.layout.Spacer 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.layout.size 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.foundation.shape.RoundedCornerShape 10 | import androidx.compose.material3.FilledTonalButton 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.text.style.TextAlign 15 | import androidx.compose.ui.unit.dp 16 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 17 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 18 | import com.itos.xplanforhyper.utils.OData 19 | 20 | fun SettingsOpt(){ 21 | // if (OData.is_have_premissipn){ 22 | // OData.configdata.data.forEach { innerList -> 23 | //// Settings.System.putString(app.contentResolver, innerList[0], Integer.valueOf(innerList[1])) 24 | // SpUtils.putSettingsParam(app, innerList[2], innerList[0], innerList[1]) 25 | // OLog.i("系统参数调优",innerList.toString()) 26 | // } 27 | // }else{ 28 | // Toast.makeText(app,"权限不足",Toast.LENGTH_SHORT).show() 29 | // } 30 | app.ShizukuExec(OData.configdata.shell.toByteArray()) 31 | MaterialAlertDialogBuilder(app) 32 | .setTitle("完成") 33 | .setMessage("调整完成") 34 | .setPositiveButton("OK",null) 35 | .show() 36 | } 37 | fun SettingsRestore (){ 38 | // if (OData.is_have_premissipn){ 39 | // OData.configdata.data.forEach { innerList -> 40 | //// Settings.System.putString(app.contentResolver, innerList[0], Integer.valueOf(innerList[1])) 41 | // SpUtils.putSettingsParam(app, innerList[2], innerList[0], innerList[1]) 42 | // OLog.i("系统参数调优",innerList.toString()) 43 | // } 44 | // }else{ 45 | // Toast.makeText(app,"权限不足",Toast.LENGTH_SHORT).show() 46 | // } 47 | app.ShizukuExec(OData.configdata.restore.toByteArray()) 48 | MaterialAlertDialogBuilder(app) 49 | .setTitle("完成") 50 | .setMessage("还原完成") 51 | .setPositiveButton("OK",null) 52 | .show() 53 | } 54 | 55 | @Composable 56 | fun Settings_opt() { 57 | Row( 58 | modifier = Modifier 59 | .padding(vertical = 45.dp) 60 | ) { 61 | FilledTonalButton( 62 | modifier = Modifier 63 | .size(width = 130.dp, height = 70.dp), 64 | shape = RoundedCornerShape(30), 65 | onClick = { 66 | SettingsOpt() 67 | Toast.makeText(app, "开发中...", Toast.LENGTH_SHORT).show() 68 | } 69 | ) { 70 | Text("系统参数\n调优", textAlign = TextAlign.Center) 71 | } 72 | Spacer(modifier = Modifier.width(25.dp)) 73 | FilledTonalButton( 74 | modifier = Modifier 75 | .size(width = 130.dp, height = 70.dp), 76 | shape = RoundedCornerShape(30), 77 | onClick = { 78 | SettingsRestore() 79 | Toast.makeText(app, "开发中...", Toast.LENGTH_SHORT).show() 80 | } 81 | ) { 82 | Text("还原\n系统参数", textAlign = TextAlign.Center) 83 | } 84 | // Spacer(modifier = Modifier.width(15.dp)) 85 | // FilledTonalButton( 86 | // modifier = Modifier 87 | // .size(width = 80.dp, height = 70.dp), 88 | // shape = RoundedCornerShape(30), 89 | // onClick = { 90 | // SettingsDebug() 91 | // Toast.makeText(app, "开发中...", Toast.LENGTH_SHORT).show() 92 | // } 93 | // ) { 94 | // Text("调试", textAlign = TextAlign.Center) 95 | // } 96 | } 97 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple80 = Color(0xFFD0BCFF) 6 | val PurpleGrey80 = Color(0xFFCCC2DC) 7 | val Pink80 = Color(0xFFEFB8C8) 8 | 9 | val Purple40 = Color(0xC86650A4) 10 | val PurpleGrey40 = Color(0xDD625B71) 11 | val Pink40 = Color(0xDD7D5260) 12 | 13 | val LightPrimary = Color(0xFF4A672D) 14 | val LightOnPrimary = Color(0xFF0E2000) 15 | val LightPrimaryContainer = Color(0xFFCBEEA5) 16 | val LightSecondary = Color(0xFF57624A) 17 | val LightTertiary = Color(0xFF386664) 18 | val LightError = Color(0xFFB3261E) 19 | 20 | val DarkPrimary = Color(0xFFAFD18C) 21 | val DarkPrimaryContainer = Color(0xFF334E17) 22 | val DarkSecondary = Color(0xFFBFCBAD) 23 | val DarkTertiary = Color(0xFFA0CFCC) 24 | val DarkError = Color(0xFFF2B8B5) -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.theme 2 | 3 | import android.app.Activity 4 | import android.os.Build 5 | import android.view.WindowManager 6 | import androidx.compose.foundation.isSystemInDarkTheme 7 | import androidx.compose.material3.MaterialTheme 8 | import androidx.compose.material3.darkColorScheme 9 | import androidx.compose.material3.dynamicDarkColorScheme 10 | import androidx.compose.material3.dynamicLightColorScheme 11 | import androidx.compose.material3.lightColorScheme 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.runtime.SideEffect 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.graphics.toArgb 16 | import androidx.compose.ui.platform.LocalContext 17 | import androidx.compose.ui.platform.LocalView 18 | import androidx.core.view.WindowCompat 19 | import com.google.accompanist.systemuicontroller.rememberSystemUiController 20 | 21 | private val DarkColorScheme = darkColorScheme( 22 | // primary = Purple80, 23 | // secondary = PurpleGrey80, 24 | // tertiary = Pink80 25 | primary = DarkPrimary, 26 | primaryContainer = DarkPrimaryContainer, 27 | secondary = DarkSecondary, 28 | tertiary = DarkTertiary, 29 | error = DarkError 30 | ) 31 | 32 | private val LightColorScheme = lightColorScheme( 33 | // primary = Purple40, 34 | // secondary = PurpleGrey40, 35 | // tertiary = Pink40 36 | primary = LightPrimary, 37 | primaryContainer = LightPrimaryContainer, 38 | secondary = LightSecondary, 39 | tertiary = LightTertiary 40 | 41 | /* Other default colors to override 42 | background = Color(0xFFFFFBFE), 43 | surface = Color(0xFFFFFBFE), 44 | onPrimary = Color.White, 45 | onSecondary = Color.White, 46 | onTertiary = Color.White, 47 | onBackground = Color(0xFF1C1B1F), 48 | onSurface = Color(0xFF1C1B1F), 49 | */ 50 | ) 51 | 52 | @Suppress("NAME_SHADOWING") 53 | @Composable 54 | fun OriginPlanTheme( 55 | // 是否处于暗色模式 56 | darkTheme: Boolean = isSystemInDarkTheme(), 57 | 58 | // Dynamic color is available on Android 12+ 59 | // 是否支持动态颜色 60 | dynamicColor: Boolean = true, 61 | // 内容 62 | content: @Composable () -> Unit 63 | ) { 64 | // 根据是否支持动态颜色,以及当前系统版本,确定颜色方案 65 | val colorScheme = when { 66 | dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { 67 | val context = LocalContext.current 68 | // 如果是暗色模式,则使用动态暗色方案,否则使用动态亮色方案 69 | if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) 70 | } 71 | 72 | darkTheme -> DarkColorScheme 73 | else -> LightColorScheme 74 | } 75 | // 获取当前视图 76 | val view = LocalView.current 77 | // 如果不是编辑模式 78 | if (!view.isInEditMode) { 79 | val systemUiController = rememberSystemUiController() 80 | val context = LocalContext.current 81 | val view = LocalView.current 82 | // 添加一个副作用,设置状态栏颜色和外观 83 | SideEffect { 84 | val window = (view.context as Activity).window 85 | 86 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 87 | window.attributes.layoutInDisplayCutoutMode = 88 | WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 89 | } 90 | 91 | WindowCompat.setDecorFitsSystemWindows(window, false) 92 | 93 | window.statusBarColor = Color.Transparent.toArgb() 94 | WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = 95 | !darkTheme 96 | } 97 | } 98 | 99 | // 设置颜色方案、类型方案和内容 100 | MaterialTheme( 101 | colorScheme = colorScheme, 102 | typography = Typography, 103 | content = content 104 | ) 105 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.ui.theme 2 | 3 | import androidx.compose.material3.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | bodyLarge = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp, 15 | lineHeight = 24.sp, 16 | letterSpacing = 0.5.sp 17 | ) 18 | /* Other default text styles to override 19 | titleLarge = TextStyle( 20 | fontFamily = FontFamily.Default, 21 | fontWeight = FontWeight.Normal, 22 | fontSize = 22.sp, 23 | lineHeight = 28.sp, 24 | letterSpacing = 0.sp 25 | ), 26 | labelSmall = TextStyle( 27 | fontFamily = FontFamily.Default, 28 | fontWeight = FontWeight.Medium, 29 | fontSize = 11.sp, 30 | lineHeight = 16.sp, 31 | letterSpacing = 0.5.sp 32 | ) 33 | */ 34 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/NetUtils.java: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.io.OutputStream; 9 | import java.net.HttpURLConnection; 10 | import java.net.URL; 11 | 12 | 13 | public class NetUtils { 14 | 15 | //Post请求1,参数俩 16 | public static String Post(String ur, String byteString) { 17 | String fh = ""; 18 | try { 19 | URL url = new URL(ur); 20 | HttpURLConnection HttpURLConnection = (HttpURLConnection) url.openConnection(); 21 | HttpURLConnection.setReadTimeout(5000); 22 | HttpURLConnection.setRequestMethod("POST"); 23 | OutputStream outputStream = HttpURLConnection.getOutputStream(); 24 | outputStream.write(byteString.getBytes()); 25 | BufferedReader BufferedReader = new BufferedReader(new InputStreamReader(HttpURLConnection.getInputStream())); 26 | String String = ""; 27 | StringBuffer StringBuffer = new StringBuffer(); 28 | while ((String = BufferedReader.readLine()) != null) { 29 | StringBuffer.append(String); 30 | } 31 | fh = StringBuffer.toString(); 32 | 33 | } catch (IOException e) { 34 | Log.d("post", String.valueOf(e)); 35 | fh="666"; 36 | } 37 | return fh; 38 | } 39 | 40 | //Post请求1,无参数 41 | public static String Post(String string) { 42 | String a=""; 43 | try { 44 | URL url = new URL(string); 45 | HttpURLConnection HttpURLConnection = (HttpURLConnection) url.openConnection(); 46 | HttpURLConnection.setReadTimeout(5000); 47 | HttpURLConnection.setRequestMethod("POST"); 48 | BufferedReader BufferedReader = new BufferedReader(new InputStreamReader(HttpURLConnection.getInputStream())); 49 | String String = ""; 50 | StringBuffer StringBuffer = new StringBuffer(); 51 | while ((String = BufferedReader.readLine()) != null) { 52 | StringBuffer.append(String); 53 | } 54 | a = StringBuffer.toString(); 55 | }catch (Exception ignored){} 56 | return a; 57 | } 58 | 59 | public static String Get(String string) throws IOException { 60 | URL url = new URL(string); 61 | HttpURLConnection HttpURLConnection = (HttpURLConnection) url.openConnection(); 62 | HttpURLConnection.setReadTimeout(5000); 63 | HttpURLConnection.setRequestMethod("GET"); 64 | BufferedReader BufferedReader = new BufferedReader(new InputStreamReader(HttpURLConnection.getInputStream())); 65 | String String = ""; 66 | StringBuffer StringBuffer = new StringBuffer(); 67 | while ((String = BufferedReader.readLine()) != null) { 68 | StringBuffer.append(String); 69 | } 70 | return StringBuffer.toString(); 71 | } 72 | 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/OData.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils 2 | 3 | import com.itos.xplanforhyper.datatype.ConfigData 4 | 5 | object OData { 6 | var configdata = ConfigData() 7 | var is_have_premissipn = false 8 | val updataUrl = "https://itos.codegang.top/share/XPlan/Hpyer/app_update.json" 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/OLog.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils 2 | 3 | import android.util.Log 4 | import com.itos.xplanforhyper.BuildConfig 5 | 6 | object OLog { 7 | fun i(tag: String, msg: String) { 8 | if (BuildConfig.DEBUG) Log.i("[调试信息]$tag", msg) 9 | } 10 | fun e(tag:String, t: Throwable) = Log.e("[错误]$tag", t.stackTraceToString()) 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/OPackage.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils 2 | 3 | import android.content.pm.PackageManager 4 | import android.graphics.drawable.Drawable 5 | 6 | object OPackage { 7 | fun isInstalled(packageName: String, packageManager: PackageManager): Boolean { 8 | try { 9 | val packageInfo = packageManager.getPackageInfo(packageName, 0) 10 | OLog.i("应用安装判断", "$packageName 已安装") 11 | return packageInfo != null 12 | } catch (ep: Throwable) { 13 | OLog.i("应用安装判断", "$packageName 未安装") 14 | } 15 | return false 16 | } 17 | 18 | fun getAppIconByPackageName(packageName: String, packageManager: PackageManager): Drawable? { 19 | return try { 20 | val applicationInfo = packageManager.getApplicationInfo(packageName, 0) 21 | packageManager.getApplicationIcon(applicationInfo) 22 | } catch (e: PackageManager.NameNotFoundException) { 23 | e.printStackTrace() 24 | null 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/OShizuku.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils 2 | 3 | import android.content.pm.PackageManager 4 | import android.os.Build 5 | import android.os.IBinder 6 | import android.os.ParcelFileDescriptor 7 | import android.os.SystemClock 8 | import android.view.InputEvent 9 | import android.view.KeyEvent 10 | import android.widget.Toast 11 | import com.itos.xplanforhyper.BuildConfig 12 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 13 | import org.lsposed.hiddenapibypass.HiddenApiBypass 14 | import rikka.shizuku.Shizuku 15 | import rikka.shizuku.ShizukuBinderWrapper 16 | import rikka.shizuku.SystemServiceHelper 17 | 18 | object OShizuku { 19 | private val myUserId = android.os.Process.myUserHandle().hashCode() 20 | private val isRoot get() = Shizuku.getUid() == 0 21 | private val userId get() = if (isRoot) myUserId else 0 22 | private val callerPackage get() = if (isRoot) BuildConfig.APPLICATION_ID else "com.android.shell" 23 | 24 | private fun asInterface(className: String, serviceName: String): Any = 25 | ShizukuBinderWrapper(SystemServiceHelper.getSystemService(serviceName)).let { 26 | Class.forName("$className\$Stub").run { 27 | if (target(Build.VERSION_CODES.P)) HiddenApiBypass.invoke( 28 | this, 29 | null, 30 | "asInterface", 31 | it 32 | ) 33 | else getMethod("asInterface", IBinder::class.java).invoke(null, it) 34 | } 35 | } 36 | 37 | private fun target(api: Int): Boolean = Build.VERSION.SDK_INT >= api 38 | val lockScreen 39 | get() = runCatching { 40 | val input = asInterface("android.hardware.input.IInputManager", "input") 41 | val inject = input::class.java.getMethod( 42 | "injectInputEvent", InputEvent::class.java, Int::class.java 43 | ) 44 | val now = SystemClock.uptimeMillis() 45 | inject.invoke( 46 | input, KeyEvent(now, now, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_POWER, 0), 0 47 | ) 48 | inject.invoke( 49 | input, KeyEvent(now, now, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_POWER, 0), 0 50 | ) 51 | true 52 | }.getOrElse { 53 | false 54 | } 55 | 56 | private fun forceStopApp(packageName: String) = runCatching { 57 | asInterface("android.app.IActivityManager", "activity").let { 58 | if (target(Build.VERSION_CODES.P)) HiddenApiBypass.invoke( 59 | it::class.java, it, "forceStopPackage", packageName, userId 60 | ) else it::class.java.getMethod( 61 | "forceStopPackage", String::class.java, Int::class.java 62 | ).invoke( 63 | it, packageName, userId 64 | ) 65 | } 66 | true 67 | }.getOrElse { 68 | false 69 | } 70 | 71 | fun setAppDisabled(packageName: String, disabled: Boolean){ 72 | 73 | if (disabled) forceStopApp(packageName) 74 | runCatching { 75 | val pm = asInterface("android.content.pm.IPackageManager", "package") 76 | val newState = when { 77 | !disabled -> PackageManager.COMPONENT_ENABLED_STATE_ENABLED 78 | isRoot -> PackageManager.COMPONENT_ENABLED_STATE_DISABLED 79 | else -> PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER 80 | } 81 | pm::class.java.getMethod( 82 | "setApplicationEnabledSetting", 83 | String::class.java, 84 | Int::class.java, 85 | Int::class.java, 86 | Int::class.java, 87 | String::class.java 88 | ).invoke(pm, packageName, newState, 0, myUserId, BuildConfig.APPLICATION_ID) 89 | }.onFailure { 90 | } 91 | 92 | } 93 | 94 | fun setAppHidden(packageName: String, hidden: Boolean): Boolean { 95 | if (hidden) forceStopApp(packageName) 96 | return runCatching { 97 | val pm = asInterface("android.content.pm.IPackageManager", "package") 98 | pm::class.java.getMethod( 99 | "setApplicationHiddenSettingAsUser", 100 | String::class.java, 101 | Boolean::class.java, 102 | Int::class.java 103 | ).invoke(pm, packageName, hidden, userId) as Boolean 104 | }.getOrElse { 105 | false 106 | } 107 | } 108 | 109 | fun checkShizuku() { 110 | try { 111 | if (Shizuku.checkSelfPermission() != PackageManager.PERMISSION_GRANTED) Shizuku.requestPermission( 112 | 0 113 | ) else app.c = true 114 | } catch (e: java.lang.Exception) { 115 | if (app.checkSelfPermission("moe.shizuku.manager.permission.API_V23") == PackageManager.PERMISSION_GRANTED) app.c = 116 | true 117 | if (e.javaClass == IllegalStateException::class.java) { 118 | app.b = false 119 | } 120 | } 121 | if (!app.b || !app.c) { 122 | Toast.makeText( 123 | app, 124 | "Shizuku " + (if (app.b) "已运行" else "未运行") + if (app.c) " 已授权" else " 未授权", 125 | Toast.LENGTH_LONG 126 | ).show() 127 | } 128 | } 129 | private val ParcelFileDescriptor.text 130 | get() = ParcelFileDescriptor.AutoCloseInputStream(this) 131 | .use { it.bufferedReader().readText() } 132 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/OTarget.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils 2 | 3 | import android.os.Build 4 | 5 | object OTarget { 6 | private fun target(api: Int): Boolean = Build.VERSION.SDK_INT >= api 7 | 8 | val N = target(Build.VERSION_CODES.N) 9 | val O = target(Build.VERSION_CODES.O) 10 | val P = target(Build.VERSION_CODES.P) 11 | val Q = target(Build.VERSION_CODES.Q) 12 | val T = target(Build.VERSION_CODES.TIRAMISU) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/OUI.kt: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils 2 | 3 | import android.content.Intent 4 | import android.graphics.BitmapFactory 5 | import android.net.Uri 6 | import android.provider.Settings 7 | import android.widget.ImageView 8 | import androidx.appcompat.app.AlertDialog 9 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 10 | import com.itos.xplanforhyper.XPlanForHyper.Companion.app 11 | import java.io.IOException 12 | 13 | 14 | object OUI { 15 | 16 | fun check_secure_premission() { 17 | try { 18 | Settings.Secure.putString(app.contentResolver, "xplan", "test") 19 | OData.is_have_premissipn = true 20 | } catch (e: Exception) { 21 | OLog.e("写入安全设置权限异常", e) 22 | OLog.i("写入安全设置权限异常", "$app.b $app.c") 23 | if (app.b && app.c) { 24 | val temp = app.ShizukuExec("pm grant com.itos.xplan android.permission.WRITE_SECURE_SETTINGS".toByteArray()) 25 | if (temp == "") { 26 | OData.is_have_premissipn = true 27 | } else { 28 | OData.is_have_premissipn = false 29 | OLog.i("设置 写入安全设置权限异常", temp!!) 30 | } 31 | } else { 32 | OShizuku.checkShizuku() 33 | } 34 | 35 | } 36 | } 37 | 38 | fun openLink(url: String) { 39 | app.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) 40 | } 41 | 42 | fun showImageDialog(imageName: String) { 43 | val builder: AlertDialog.Builder = MaterialAlertDialogBuilder(app) 44 | 45 | // 创建一个 ImageView 并添加到对话框中 46 | val imageView = ImageView(app) 47 | try { 48 | val `is` = app.assets.open(imageName) 49 | val bitmap = BitmapFactory.decodeStream(`is`) 50 | imageView.setImageBitmap(bitmap) 51 | imageView.scaleType = ImageView.ScaleType.FIT_CENTER 52 | } catch (e: IOException) { 53 | e.printStackTrace() 54 | } 55 | builder.setView(imageView) // 将 ImageView 加到对话框中 56 | builder.setNegativeButton("OK") { dialog, which -> 57 | // 点击 OK 按钮后的操作 58 | dialog.dismiss() 59 | } 60 | builder.show() // 显示对话框 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/itos/xplanforhyper/utils/SpUtils.java: -------------------------------------------------------------------------------- 1 | package com.itos.xplanforhyper.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.provider.Settings; 6 | 7 | public class SpUtils { 8 | 9 | /** 10 | * 保存在手机里面的文件名 11 | */ 12 | private static final String FILE_NAME = "share_date"; 13 | 14 | 15 | /** 16 | * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法 17 | * @param context 18 | * @param key 19 | * @param object 20 | */ 21 | public static void setParam(Context context , String key, Object object){ 22 | 23 | String type = object.getClass().getSimpleName(); 24 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); 25 | SharedPreferences.Editor editor = sp.edit(); 26 | 27 | switch (type) { 28 | case "String": 29 | editor.putString(key, (String) object); 30 | break; 31 | case "Integer": 32 | editor.putInt(key, (Integer) object); 33 | break; 34 | case "Boolean": 35 | editor.putBoolean(key, (Boolean) object); 36 | break; 37 | case "Float": 38 | editor.putFloat(key, (Float) object); 39 | break; 40 | case "Long": 41 | editor.putLong(key, (Long) object); 42 | break; 43 | } 44 | 45 | editor.apply(); 46 | } 47 | 48 | 49 | /** 50 | * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值 51 | * @param context 52 | * @param key 53 | * @param defaultObject 54 | * @return 55 | */ 56 | public static Object getParam(Context context , String key, Object defaultObject){ 57 | String type = defaultObject.getClass().getSimpleName(); 58 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); 59 | 60 | switch (type) { 61 | case "String": 62 | return sp.getString(key, (String) defaultObject); 63 | case "Integer": 64 | return sp.getInt(key, (Integer) defaultObject); 65 | case "Boolean": 66 | return sp.getBoolean(key, (Boolean) defaultObject); 67 | case "Float": 68 | return sp.getFloat(key, (Float) defaultObject); 69 | case "Long": 70 | return sp.getLong(key, (Long) defaultObject); 71 | } 72 | 73 | return null; 74 | } 75 | 76 | public static void putSettingsParam(Context context , String fenqu,String key, Object object){ 77 | String type = object.getClass().getSimpleName(); 78 | switch (fenqu) { 79 | case "system": 80 | switch (type) { 81 | case "String": 82 | case "Boolean": 83 | Settings.System.putString(context.getContentResolver(), key, (String) object); 84 | break; 85 | case "Integer": 86 | Settings.System.putInt(context.getContentResolver(), key, (Integer) object); 87 | break; 88 | case "Float": 89 | Settings.System.putFloat(context.getContentResolver(), key, (Float) object); 90 | break; 91 | case "Long": 92 | Settings.System.putLong(context.getContentResolver(), key, (Long) object); 93 | break; 94 | } 95 | case "global": 96 | switch (type) { 97 | case "String": 98 | case "Boolean": 99 | Settings.Global.putString(context.getContentResolver(), key, (String) object); 100 | break; 101 | case "Integer": 102 | Settings.Global.putInt(context.getContentResolver(), key, (Integer) object); 103 | break; 104 | case "Float": 105 | Settings.Global.putFloat(context.getContentResolver(), key, (Float) object); 106 | break; 107 | case "Long": 108 | Settings.Global.putLong(context.getContentResolver(), key, (Long) object); 109 | break; 110 | } 111 | case "secure": 112 | switch (type) { 113 | case "String": 114 | case "Boolean": 115 | Settings.Secure.putString(context.getContentResolver(), key, (String) object); 116 | break; 117 | case "Integer": 118 | Settings.Secure.putInt(context.getContentResolver(), key, (Integer) object); 119 | break; 120 | case "Float": 121 | Settings.Secure.putFloat(context.getContentResolver(), key, (Float) object); 122 | break; 123 | case "Long": 124 | Settings.Secure.putLong(context.getContentResolver(), key, (Long) object); 125 | break; 126 | } 127 | } 128 | } 129 | public static String getSettingsParam(Context context , String fenqu,String key){ 130 | switch (fenqu) { 131 | case "system": 132 | return Settings.System.getString(context.getContentResolver(), key); 133 | case "global": 134 | return Settings.Global.getString(context.getContentResolver(), key); 135 | case "secure": 136 | return Settings.Secure.getString(context.getContentResolver(), key); 137 | default: 138 | return "null"; 139 | } 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_alipay.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_info.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_terminal.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bilibili.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_code.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_coolapk.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_giftcard.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_info.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_lisence.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_qq.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wechatpay.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_xplan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_xplan_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_xplan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-hdpi/ic_launcher_xplan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_xplan_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-hdpi/ic_launcher_xplan_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_xplan_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-hdpi/ic_launcher_xplan_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_xplan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-mdpi/ic_launcher_xplan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_xplan_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-mdpi/ic_launcher_xplan_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_xplan_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-mdpi/ic_launcher_xplan_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_xplan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xhdpi/ic_launcher_xplan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_xplan_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xhdpi/ic_launcher_xplan_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_xplan_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xhdpi/ic_launcher_xplan_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xplan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxhdpi/ic_launcher_xplan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xplan_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxhdpi/ic_launcher_xplan_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xplan_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxhdpi/ic_launcher_xplan_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xplan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xplan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xplan_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xplan_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xplan_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xplan_round.png -------------------------------------------------------------------------------- /app/src/main/res/raw/licenses: -------------------------------------------------------------------------------- 1 | Android Jetpack (Apache 2.0): https://developer.android.com/jetpack 2 | 3 | Material Components for Android (Apache 2.0): https://github.com/material-components/material-components-android 4 | 5 | Shizuku (Apache 2.0): https://github.com/RikkaApps/Shizuku 6 | 7 | Shizuku-API (MIT): https://github.com/RikkaApps/Shizuku-API 8 | 9 | Kotlin (Apache 2.0): https://kotlinlang.org 10 | 11 | AndroidHiddenApiBypass (Apache 2.0): https://github.com/LSPosed/AndroidHiddenApiBypass 12 | 13 | Hail (GPL 3.0): https://github.com/aistra0528/Hail 14 | 15 | InstallerX (GPL 3.0): https://github.com/iamr0s/InstallerX -------------------------------------------------------------------------------- /app/src/main/res/raw/moreapp: -------------------------------------------------------------------------------- 1 | vivo免root去温控: https://www.123pan.com/s/vYnqVv-b9hKd.html 2 | 3 | 系统优化APP:https://www.123pan.com/s/vYnqVv-PZhKd.html 4 | 5 | 蓝厂工具盒:https://www.123pan.com/s/vYnqVv-GZhKd.html 6 | 7 | DPM操作:https://codegang.lanzouq.com/i775411t1ucf?password=aii7 8 | 9 | PS:请下载网盘中最新版本号的apk安装 -------------------------------------------------------------------------------- /app/src/main/res/raw/optlist: -------------------------------------------------------------------------------- 1 | com.miui.video 2 | com.miui.player 3 | com.android.quicksearchbox 4 | com.miui.touchassistant 5 | com.miui.nextpay 6 | com.miui.newhome 7 | com.xiaomi.payment 8 | com.miui.yellowpage 9 | com.miui.hybrid.accessory 10 | com.xiaomi.vipaccount 11 | com.miui.hybrid 12 | com.xiaomi.scanner 13 | com.xiaomi.mibrain.speech 14 | com.miui.personalassistant 15 | com.miui.mishare.connectivity 16 | com.mipay.wallet 17 | com.miui.virtualsim -------------------------------------------------------------------------------- /app/src/main/res/raw/pkglist: -------------------------------------------------------------------------------- 1 | com.xiaomi.joyose 2 | com.miui.voiceassist 3 | com.xiaomi.aiasst.vision 4 | com.android.browser 5 | com.miui.notes 6 | com.miui.contentextension 7 | com.android.email 8 | com.miui.voicetrigger 9 | com.android.updater -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | 11 | #00000000 12 | @color/error_color_material_light 13 | 14 | 15 | #FF4A672D 16 | #FF0E2000 17 | #FFCBEEA5 18 | #FF57624A 19 | #FF386664 20 | #FFB3261E 21 | 22 | #FFAFD18C 23 | #FF334E17 24 | #FFBFCBAD 25 | #FFA0CFCC 26 | #FFF2B8B5 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_xplan_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #36374C 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | XHyper 3 | 许可证 4 | Beta 5 | 操作失败:%s 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [["test1", "1", "global"],["test2","2","system"],["test3","3","secure"]], 3 | "shell": "echo test", 4 | "restore ":"echo restore", 5 | "debug": "echo debug" 6 | } 7 | -------------------------------------------------------------------------------- /app_update.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "22", 3 | "version_name": "Alpha-2.2", 4 | "url": "https://www.123pan.com/s/vYnqVv-vLhKd.html", 5 | "log": "加入 终端 功能\n优化部分实现方法", 6 | "isShowNotice": "true", 7 | "notice": "OS4不要用进程调整\nOS4可能效果不明显\n毕竟是新系统,没有什么负优化\n可以等后续推送一些实用小功能\n\n横屏显示有问题,可能不会修了" 8 | } -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | maven { url =uri("https://dl.bintray.com/rikkaw/Shizuku") } 7 | maven { url = uri("https://jitpack.io") } 8 | 9 | } 10 | } 11 | plugins { 12 | id("com.android.application") version "8.1.1" apply false 13 | id("org.jetbrains.kotlin.android") version "1.8.10" apply false 14 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## For more details on how to configure your build environment visit 2 | # http://www.gradle.org/docs/current/userguide/build_environment.html 3 | # 4 | # Specifies the JVM arguments used for the daemon process. 5 | # The setting is particularly useful for tweaking memory settings. 6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 7 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 8 | # 9 | # When configured, Gradle will run in incubating parallel mode. 10 | # This option should only be used with decoupled projects. More details, visit 11 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 12 | # org.gradle.parallel=true 13 | #Sat Dec 30 21:06:08 CST 2023 14 | android.defaults.buildfeatures.buildconfig=true 15 | android.enableR8.fullMode=true 16 | android.nonTransitiveRClass=true 17 | android.useAndroidX=true 18 | kotlin.code.style=official 19 | org.gradle.jvmargs=-Xmx3072M -Dkotlin.daemon.jvm.options\="-Xmx2048M" -XX\:MaxPermSize\=512m -XX\:+HeapDumpOnOutOfMemoryError -Dfile.encoding\=UTF-8 20 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItosEO/XPlanForHyper/df9b94a67356b7a20de29126c1bbdab7ea19f28c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Nov 29 09:58:34 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 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | maven { url = uri("https://jitpack.io") } 7 | maven { url =uri("https://dl.bintray.com/rikkaw/Shizuku") } 8 | 9 | } 10 | } 11 | dependencyResolutionManagement { 12 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | } 18 | 19 | rootProject.name = "XPlanForHyper" 20 | include(":app") 21 | --------------------------------------------------------------------------------