mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
merge branch 'auth'
This commit is contained in:
@@ -21,21 +21,24 @@ android {
|
|||||||
applicationId = "com.bintianqi.owndroid"
|
applicationId = "com.bintianqi.owndroid"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 27
|
versionCode = 28
|
||||||
versionName = "5.2"
|
versionName = "5.3"
|
||||||
multiDexEnabled = false
|
multiDexEnabled = false
|
||||||
signingConfig = signingConfigs.getByName("testkey")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
project.gradle.startParameter.excludedTaskNames.add("lint")
|
//project.gradle.startParameter.excludedTaskNames.add("lint")
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
isShrinkResources = true
|
isShrinkResources = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
)
|
)
|
||||||
|
signingConfig = signingConfigs.getByName("testkey")
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
signingConfig = signingConfigs.getByName("testkey")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -75,4 +78,5 @@ dependencies {
|
|||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.shizuku.provider)
|
implementation(libs.shizuku.provider)
|
||||||
implementation(libs.shizuku.api)
|
implementation(libs.shizuku.api)
|
||||||
|
implementation(libs.androidx.biometric)
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".Receiver"
|
android:name=".Receiver"
|
||||||
android:description="@string/app_name"
|
android:description="@string/app_name"
|
||||||
|
|||||||
153
app/src/main/java/com/bintianqi/owndroid/Auth.kt
Normal file
153
app/src/main/java/com/bintianqi/owndroid/Auth.kt
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
package com.bintianqi.owndroid
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.biometric.BiometricManager
|
||||||
|
import androidx.biometric.BiometricPrompt
|
||||||
|
import androidx.biometric.BiometricPrompt.AuthenticationCallback
|
||||||
|
import androidx.biometric.BiometricPrompt.PromptInfo.Builder
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class AuthFragment: Fragment() {
|
||||||
|
@SuppressLint("UnrememberedMutableState")
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
val context = requireContext()
|
||||||
|
val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)!!
|
||||||
|
val canStartAuth = mutableStateOf(true)
|
||||||
|
val onAuthSucceed = {
|
||||||
|
val fragmentManager = this.parentFragmentManager
|
||||||
|
val transaction = fragmentManager.beginTransaction()
|
||||||
|
transaction.setCustomAnimations(R.anim.enter, R.anim.exit)
|
||||||
|
transaction.remove(this@AuthFragment).commit()
|
||||||
|
}
|
||||||
|
val promptInfo = Builder()
|
||||||
|
.setTitle(context.getText(R.string.authenticate))
|
||||||
|
.setSubtitle(context.getText(R.string.auth_with_bio))
|
||||||
|
.setConfirmationRequired(true)
|
||||||
|
var fallback = false
|
||||||
|
val callback = object: AuthenticationCallback() {
|
||||||
|
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||||
|
super.onAuthenticationSucceeded(result)
|
||||||
|
onAuthSucceed()
|
||||||
|
}
|
||||||
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
|
super.onAuthenticationError(errorCode, errString)
|
||||||
|
when(errorCode){
|
||||||
|
BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL -> onAuthSucceed()
|
||||||
|
BiometricPrompt.ERROR_NEGATIVE_BUTTON -> fallback = true
|
||||||
|
else -> canStartAuth.value = true
|
||||||
|
}
|
||||||
|
Log.e("OwnDroid", errString.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
while(true){
|
||||||
|
if(fallback){
|
||||||
|
val fallbackPromptInfo = Builder()
|
||||||
|
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
|
||||||
|
.setTitle(context.getText(R.string.authenticate))
|
||||||
|
.setSubtitle(context.getText(R.string.auth_with_password))
|
||||||
|
.setConfirmationRequired(true)
|
||||||
|
.build()
|
||||||
|
val executor = ContextCompat.getMainExecutor(requireContext())
|
||||||
|
val biometricPrompt = BiometricPrompt(requireActivity(), executor, callback)
|
||||||
|
biometricPrompt.authenticate(fallbackPromptInfo)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
delay(50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ComposeView(requireContext()).apply {
|
||||||
|
setContent {
|
||||||
|
val materialYou = mutableStateOf(sharedPref.getBoolean("material_you",true))
|
||||||
|
val blackTheme = mutableStateOf(sharedPref.getBoolean("black_theme", false))
|
||||||
|
OwnDroidTheme(materialYou.value, blackTheme.value) {
|
||||||
|
Auth(this@AuthFragment, promptInfo, callback, canStartAuth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Auth(activity: Fragment, promptInfo: Builder, callback: AuthenticationCallback, canStartAuth: MutableState<Boolean>) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
|
||||||
|
){
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.authenticate),
|
||||||
|
style = MaterialTheme.typography.headlineLarge,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
LaunchedEffect(Unit){
|
||||||
|
delay(300)
|
||||||
|
startAuth(activity, promptInfo, callback)
|
||||||
|
canStartAuth.value = false
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
startAuth(activity, promptInfo, callback)
|
||||||
|
canStartAuth.value = false
|
||||||
|
},
|
||||||
|
enabled = canStartAuth.value
|
||||||
|
){
|
||||||
|
Text(text = stringResource(R.string.start))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startAuth(activity: Fragment, promptInfo: Builder, callback: AuthenticationCallback){
|
||||||
|
val context = activity.requireContext()
|
||||||
|
val bioManager = BiometricManager.from(context)
|
||||||
|
val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
|
if(sharedPref.getBoolean("bio_auth", false)){
|
||||||
|
when(BiometricManager.BIOMETRIC_SUCCESS){
|
||||||
|
bioManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) ->
|
||||||
|
promptInfo
|
||||||
|
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
||||||
|
.setNegativeButtonText(context.getText(R.string.use_password))
|
||||||
|
bioManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) ->
|
||||||
|
promptInfo
|
||||||
|
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK)
|
||||||
|
.setNegativeButtonText(context.getText(R.string.use_password))
|
||||||
|
else -> promptInfo
|
||||||
|
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
|
||||||
|
.setSubtitle(context.getText(R.string.auth_with_password))
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
promptInfo
|
||||||
|
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
|
||||||
|
.setSubtitle(context.getText(R.string.auth_with_password))
|
||||||
|
}
|
||||||
|
val executor = ContextCompat.getMainExecutor(context)
|
||||||
|
val biometricPrompt = BiometricPrompt(activity, executor, callback)
|
||||||
|
biometricPrompt.authenticate(promptInfo.build())
|
||||||
|
}
|
||||||
@@ -6,9 +6,11 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -27,12 +29,15 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
@@ -45,21 +50,65 @@ import java.util.Locale
|
|||||||
|
|
||||||
var backToHome = false
|
var backToHome = false
|
||||||
@ExperimentalMaterial3Api
|
@ExperimentalMaterial3Api
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : FragmentActivity() {
|
||||||
|
private var auth = false
|
||||||
@SuppressLint("UnrememberedMutableState")
|
@SuppressLint("UnrememberedMutableState")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
registerActivityResult(this)
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
registerActivityResult(this)
|
setContentView(R.layout.base)
|
||||||
val locale = applicationContext.resources.configuration.locale
|
|
||||||
zhCN = locale==Locale.SIMPLIFIED_CHINESE||locale==Locale.CHINESE||locale==Locale.CHINA
|
|
||||||
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
|
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
setContent {
|
val fragmentManager = supportFragmentManager
|
||||||
val materialYou = mutableStateOf(sharedPref.getBoolean("material_you",true))
|
val transaction = fragmentManager.beginTransaction()
|
||||||
val blackTheme = mutableStateOf(sharedPref.getBoolean("black_theme", false))
|
transaction.add(R.id.base, HomeFragment(), "home")
|
||||||
OwnDroidTheme(materialYou.value, blackTheme.value){
|
if(sharedPref.getBoolean("auth", false)){
|
||||||
Home(materialYou, blackTheme)
|
transaction.add(R.id.base, AuthFragment(), "auth")
|
||||||
|
}
|
||||||
|
transaction.commit()
|
||||||
|
val locale = applicationContext.resources?.configuration?.locale
|
||||||
|
zhCN = locale==Locale.SIMPLIFIED_CHINESE||locale==Locale.CHINESE||locale==Locale.CHINA
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(auth){
|
||||||
|
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
|
if(
|
||||||
|
sharedPref.getBoolean("auth", false) &&
|
||||||
|
sharedPref.getBoolean("lock_in_background", false)
|
||||||
|
){
|
||||||
|
val fragmentManager = supportFragmentManager
|
||||||
|
val fragment = fragmentManager.findFragmentByTag("auth")
|
||||||
|
if(fragment == null){
|
||||||
|
val transaction = fragmentManager.beginTransaction()
|
||||||
|
transaction.setCustomAnimations(R.anim.enter, R.anim.exit)
|
||||||
|
transaction.add(R.id.base, AuthFragment(), "auth").commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auth = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestart() {
|
||||||
|
super.onRestart()
|
||||||
|
auth = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeFragment: Fragment() {
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@SuppressLint("UnrememberedMutableState")
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
val sharedPref = context?.getSharedPreferences("data", Context.MODE_PRIVATE)!!
|
||||||
|
return ComposeView(requireContext()).apply {
|
||||||
|
setContent {
|
||||||
|
val materialYou = mutableStateOf(sharedPref.getBoolean("material_you",true))
|
||||||
|
val blackTheme = mutableStateOf(sharedPref.getBoolean("black_theme", false))
|
||||||
|
OwnDroidTheme(materialYou.value, blackTheme.value){
|
||||||
|
Home(materialYou, blackTheme)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,18 +145,18 @@ fun Home(materialYou:MutableState<Boolean>, blackTheme:MutableState<Boolean>){
|
|||||||
popEnterTransition = Animations.navHostPopEnterTransition,
|
popEnterTransition = Animations.navHostPopEnterTransition,
|
||||||
popExitTransition = Animations.navHostPopExitTransition
|
popExitTransition = Animations.navHostPopExitTransition
|
||||||
){
|
){
|
||||||
composable(route = "HomePage", content = { HomePage(navCtrl, pkgName)})
|
composable(route = "HomePage"){ HomePage(navCtrl, pkgName) }
|
||||||
composable(route = "SystemManage", content = { SystemManage(navCtrl) })
|
composable(route = "SystemManage"){ SystemManage(navCtrl) }
|
||||||
composable(route = "ManagedProfile", content = {ManagedProfile(navCtrl)})
|
composable(route = "ManagedProfile"){ ManagedProfile(navCtrl) }
|
||||||
composable(route = "Permissions", content = { DpmPermissions(navCtrl)})
|
composable(route = "Permissions"){ DpmPermissions(navCtrl) }
|
||||||
composable(route = "ApplicationManage", content = { ApplicationManage(navCtrl, pkgName, dialogStatus)})
|
composable(route = "ApplicationManage"){ ApplicationManage(navCtrl, pkgName, dialogStatus)}
|
||||||
composable(route = "UserRestriction", content = { UserRestriction(navCtrl)})
|
composable(route = "UserRestriction"){ UserRestriction(navCtrl) }
|
||||||
composable(route = "UserManage", content = { UserManage(navCtrl)})
|
composable(route = "UserManage"){ UserManage(navCtrl) }
|
||||||
composable(route = "Password", content = { Password(navCtrl)})
|
composable(route = "Password"){ Password(navCtrl) }
|
||||||
composable(route = "AppSetting", content = { AppSetting(navCtrl, materialYou, blackTheme)})
|
composable(route = "AppSetting"){ AppSetting(navCtrl, materialYou, blackTheme) }
|
||||||
composable(route = "Network", content = {Network(navCtrl)})
|
composable(route = "Network"){ Network(navCtrl) }
|
||||||
composable(route = "PackageSelector"){PackageSelector(navCtrl, pkgName)}
|
composable(route = "PackageSelector"){ PackageSelector(navCtrl, pkgName) }
|
||||||
composable(route = "PermissionPicker"){PermissionPicker(navCtrl)}
|
composable(route = "PermissionPicker"){ PermissionPicker(navCtrl) }
|
||||||
}
|
}
|
||||||
LaunchedEffect(Unit){
|
LaunchedEffect(Unit){
|
||||||
val profileInited = sharedPref.getBoolean("ManagedProfileActivated",false)
|
val profileInited = sharedPref.getBoolean("ManagedProfileActivated",false)
|
||||||
|
|||||||
@@ -5,18 +5,13 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -26,10 +21,7 @@ import androidx.navigation.compose.NavHost
|
|||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.bintianqi.owndroid.ui.Animations
|
import com.bintianqi.owndroid.ui.*
|
||||||
import com.bintianqi.owndroid.ui.SubPageItem
|
|
||||||
import com.bintianqi.owndroid.ui.SwitchItem
|
|
||||||
import com.bintianqi.owndroid.ui.TopBar
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppSetting(navCtrl:NavHostController, materialYou: MutableState<Boolean>, blackTheme: MutableState<Boolean>){
|
fun AppSetting(navCtrl:NavHostController, materialYou: MutableState<Boolean>, blackTheme: MutableState<Boolean>){
|
||||||
@@ -56,9 +48,10 @@ fun AppSetting(navCtrl:NavHostController, materialYou: MutableState<Boolean>, bl
|
|||||||
popExitTransition = Animations.navHostPopExitTransition,
|
popExitTransition = Animations.navHostPopExitTransition,
|
||||||
modifier = Modifier.padding(top = it.calculateTopPadding())
|
modifier = Modifier.padding(top = it.calculateTopPadding())
|
||||||
){
|
){
|
||||||
composable(route = "Home"){Home(localNavCtrl)}
|
composable(route = "Home"){ Home(localNavCtrl) }
|
||||||
composable(route = "Settings"){Settings(materialYou, blackTheme)}
|
composable(route = "Theme"){ ThemeSettings(materialYou, blackTheme) }
|
||||||
composable(route = "About"){About()}
|
composable(route = "Auth"){ AuthSettings() }
|
||||||
|
composable(route = "About"){ About() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,13 +59,14 @@ fun AppSetting(navCtrl:NavHostController, materialYou: MutableState<Boolean>, bl
|
|||||||
@Composable
|
@Composable
|
||||||
private fun Home(navCtrl: NavHostController){
|
private fun Home(navCtrl: NavHostController){
|
||||||
Column(modifier = Modifier.fillMaxSize()){
|
Column(modifier = Modifier.fillMaxSize()){
|
||||||
SubPageItem(R.string.setting,"",R.drawable.settings_fill0){navCtrl.navigate("Settings")}
|
SubPageItem(R.string.theme,"",R.drawable.format_paint_fill0){navCtrl.navigate("Theme")}
|
||||||
|
SubPageItem(R.string.security,"",R.drawable.lock_fill0){navCtrl.navigate("Auth")}
|
||||||
SubPageItem(R.string.about,"",R.drawable.info_fill0){navCtrl.navigate("About")}
|
SubPageItem(R.string.about,"",R.drawable.info_fill0){navCtrl.navigate("About")}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Settings(materialYou:MutableState<Boolean>, blackTheme:MutableState<Boolean>){
|
private fun ThemeSettings(materialYou:MutableState<Boolean>, blackTheme:MutableState<Boolean>){
|
||||||
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
|
||||||
if(VERSION.SDK_INT>=31){
|
if(VERSION.SDK_INT>=31){
|
||||||
@@ -98,6 +92,39 @@ private fun Settings(materialYou:MutableState<Boolean>, blackTheme:MutableState<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun AuthSettings(){
|
||||||
|
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
|
var auth by remember{ mutableStateOf(sharedPref.getBoolean("auth",false)) }
|
||||||
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
|
||||||
|
SwitchItem(
|
||||||
|
R.string.lock_owndroid, "", null,
|
||||||
|
{ auth },
|
||||||
|
{
|
||||||
|
sharedPref.edit().putBoolean("auth",it).apply()
|
||||||
|
auth = sharedPref.getBoolean("auth",false)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if(auth){
|
||||||
|
SwitchItem(
|
||||||
|
R.string.enable_bio_auth, "", null,
|
||||||
|
{ sharedPref.getBoolean("bio_auth",false) },
|
||||||
|
{ sharedPref.edit().putBoolean("bio_auth",it).apply() }
|
||||||
|
)
|
||||||
|
SwitchItem(
|
||||||
|
R.string.lock_in_background, "", null,
|
||||||
|
{ sharedPref.getBoolean("lock_in_background",false) },
|
||||||
|
{ sharedPref.edit().putBoolean("lock_in_background",it).apply() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Box(modifier = Modifier.padding(horizontal = 8.dp)){
|
||||||
|
Information {
|
||||||
|
Text(text = stringResource(R.string.auth_on_start))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun About(){
|
private fun About(){
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|||||||
18
app/src/main/res/anim/enter.xml
Normal file
18
app/src/main/res/anim/enter.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<scale
|
||||||
|
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||||
|
android:fromXScale="0.95"
|
||||||
|
android:toXScale="1.0"
|
||||||
|
android:fromYScale="0.95"
|
||||||
|
android:toYScale="1.0"
|
||||||
|
android:pivotX="50%"
|
||||||
|
android:pivotY="50%"
|
||||||
|
android:fillAfter="false"
|
||||||
|
android:duration="200" />
|
||||||
|
<alpha
|
||||||
|
android:duration="150"
|
||||||
|
android:fromAlpha="0.0"
|
||||||
|
android:interpolator="@android:anim/accelerate_interpolator"
|
||||||
|
android:toAlpha="1.0" />
|
||||||
|
</set>
|
||||||
8
app/src/main/res/anim/exit.xml
Normal file
8
app/src/main/res/anim/exit.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<alpha
|
||||||
|
android:duration="250"
|
||||||
|
android:fromAlpha="1.0"
|
||||||
|
android:interpolator="@android:anim/accelerate_interpolator"
|
||||||
|
android:toAlpha="0.0" />
|
||||||
|
</set>
|
||||||
9
app/src/main/res/drawable/format_paint_fill0.xml
Normal file
9
app/src/main/res/drawable/format_paint_fill0.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:pathData="M440,880q-33,0 -56.5,-23.5T360,800v-160L240,640q-33,0 -56.5,-23.5T160,560v-280q0,-66 47,-113t113,-47h480v440q0,33 -23.5,56.5T720,640L600,640v160q0,33 -23.5,56.5T520,880h-80ZM240,400h480v-200h-40v160h-80v-160h-40v80h-80v-80L320,200q-33,0 -56.5,23.5T240,280v120ZM240,560h480v-80L240,480v80ZM240,560v-80,80Z"
|
||||||
|
android:fillColor="#FF000000"/>
|
||||||
|
</vector>
|
||||||
8
app/src/main/res/layout/base.xml
Normal file
8
app/src/main/res/layout/base.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/base"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
<string name="file_not_exist">文件不存在</string>
|
<string name="file_not_exist">文件不存在</string>
|
||||||
<string name="io_exception">IO异常</string>
|
<string name="io_exception">IO异常</string>
|
||||||
<string name="current_status_is">当前状态:</string>
|
<string name="current_status_is">当前状态:</string>
|
||||||
|
<string name="start">开始</string>
|
||||||
|
|
||||||
<!--Permissions-->
|
<!--Permissions-->
|
||||||
<string name="click_to_activate">点击以激活</string>
|
<string name="click_to_activate">点击以激活</string>
|
||||||
@@ -478,9 +479,20 @@
|
|||||||
<string name="about_desc">使用安卓的Device admin、Device owner、Profile owner,全方位掌控你的设备</string>
|
<string name="about_desc">使用安卓的Device admin、Device owner、Profile owner,全方位掌控你的设备</string>
|
||||||
<string name="user_guide">使用教程</string>
|
<string name="user_guide">使用教程</string>
|
||||||
<string name="source_code">源代码</string>
|
<string name="source_code">源代码</string>
|
||||||
|
<string name="theme">主题</string>
|
||||||
<string name="amoled_black">纯黑夜间主题</string>
|
<string name="amoled_black">纯黑夜间主题</string>
|
||||||
<string name="blackTheme_desc">需要打开夜间模式</string>
|
<string name="blackTheme_desc">需要打开夜间模式</string>
|
||||||
|
|
||||||
|
<string name="security">安全</string>
|
||||||
|
<string name="lock_owndroid">锁定OwnDroid</string>
|
||||||
|
<string name="enable_bio_auth">使用生物识别</string>
|
||||||
|
<string name="authenticate">验证</string>
|
||||||
|
<string name="auth_on_start">在OwnDroid启动时使用锁屏密码或生物识别进行验证</string>
|
||||||
|
<string name="use_password">使用密码</string>
|
||||||
|
<string name="auth_with_password">使用密码进行验证</string>
|
||||||
|
<string name="auth_with_bio">使用生物识别进行验证</string>
|
||||||
|
<string name="lock_in_background">处于后台时锁定</string>
|
||||||
|
|
||||||
<!--AndroidPermission-->
|
<!--AndroidPermission-->
|
||||||
<string name="permission_READ_EXTERNAL_STORAGE">读取外部存储</string>
|
<string name="permission_READ_EXTERNAL_STORAGE">读取外部存储</string>
|
||||||
<string name="permission_WRITE_EXTERNAL_STORAGE">写入外部存储</string>
|
<string name="permission_WRITE_EXTERNAL_STORAGE">写入外部存储</string>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
<string name="file_not_exist">File not exist</string>
|
<string name="file_not_exist">File not exist</string>
|
||||||
<string name="io_exception">IO Exception</string>
|
<string name="io_exception">IO Exception</string>
|
||||||
<string name="current_status_is">Current status: </string>
|
<string name="current_status_is">Current status: </string>
|
||||||
|
<string name="start">Start</string>
|
||||||
|
|
||||||
<!--Permissions-->
|
<!--Permissions-->
|
||||||
<string name="click_to_activate">Click to activate</string>
|
<string name="click_to_activate">Click to activate</string>
|
||||||
@@ -493,9 +494,20 @@
|
|||||||
<string name="about_desc">Use Device admin, Profile owner and Device owner privilege to take full control of your device. </string>
|
<string name="about_desc">Use Device admin, Profile owner and Device owner privilege to take full control of your device. </string>
|
||||||
<string name="user_guide">User guide</string>
|
<string name="user_guide">User guide</string>
|
||||||
<string name="source_code">Source code</string>
|
<string name="source_code">Source code</string>
|
||||||
|
<string name="theme">Theme</string>
|
||||||
<string name="amoled_black">Black theme</string>
|
<string name="amoled_black">Black theme</string>
|
||||||
<string name="blackTheme_desc">Require dark mode on</string>
|
<string name="blackTheme_desc">Require dark mode on</string>
|
||||||
|
|
||||||
|
<string name="security">Security</string>
|
||||||
|
<string name="lock_owndroid">Lock OwnDroid</string>
|
||||||
|
<string name="enable_bio_auth">Auth with biometrics</string>
|
||||||
|
<string name="authenticate">Authenticate</string>
|
||||||
|
<string name="auth_on_start">Authenticating with keyguard password or biometrics when OwnDroid launch</string>
|
||||||
|
<string name="use_password">Use password</string>
|
||||||
|
<string name="auth_with_password">Authenticate OwnDroid with password</string>
|
||||||
|
<string name="auth_with_bio">Authenticate OwnDroid with biometrics</string>
|
||||||
|
<string name="lock_in_background">Lock when switch to background</string>
|
||||||
|
|
||||||
<!--AndroidPermission-->
|
<!--AndroidPermission-->
|
||||||
<string name="permission_READ_EXTERNAL_STORAGE">Read external storage</string>
|
<string name="permission_READ_EXTERNAL_STORAGE">Read external storage</string>
|
||||||
<string name="permission_WRITE_EXTERNAL_STORAGE">Write external storage</string>
|
<string name="permission_WRITE_EXTERNAL_STORAGE">Write external storage</string>
|
||||||
|
|||||||
@@ -3,6 +3,5 @@
|
|||||||
<style name="Theme.OwnDroid" parent="android:Theme.Material.Light.NoActionBar">
|
<style name="Theme.OwnDroid" parent="android:Theme.Material.Light.NoActionBar">
|
||||||
<item name="android:navigationBarColor">#FFFFFF</item>
|
<item name="android:navigationBarColor">#FFFFFF</item>
|
||||||
<item name="android:statusBarColor">#FFFFFF</item>
|
<item name="android:statusBarColor">#FFFFFF</item>
|
||||||
<item name="android:windowSwipeToDismiss">true</item>
|
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ navigation-compose = "2.7.7"
|
|||||||
material3 = "1.2.1"
|
material3 = "1.2.1"
|
||||||
accompanist-drawablepainter = "0.35.0-alpha"
|
accompanist-drawablepainter = "0.35.0-alpha"
|
||||||
shizuku = "13.1.5"
|
shizuku = "13.1.5"
|
||||||
|
biometric = "1.2.0-alpha05"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" }
|
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" }
|
||||||
@@ -16,6 +17,7 @@ androidx-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
|
|||||||
androidx-ui = { module = "androidx.compose.ui:ui" }
|
androidx-ui = { module = "androidx.compose.ui:ui" }
|
||||||
|
|
||||||
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }
|
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }
|
||||||
|
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "biometric" }
|
||||||
|
|
||||||
shizuku-provider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" }
|
shizuku-provider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" }
|
||||||
shizuku-api = { module = "dev.rikka.shizuku:api", version.ref = "shizuku" }
|
shizuku-api = { module = "dev.rikka.shizuku:api", version.ref = "shizuku" }
|
||||||
|
|||||||
Reference in New Issue
Block a user