mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
simplify code of getting file
optimize animation
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
@@ -10,7 +9,6 @@ import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
@@ -49,28 +47,11 @@ import kotlinx.coroutines.delay
|
||||
var backToHome = false
|
||||
@ExperimentalMaterial3Api
|
||||
class MainActivity : ComponentActivity() {
|
||||
private fun registerActivityResult(){
|
||||
getUserIcon = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { userIconUri = it.data?.data }
|
||||
getApk = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { apkUri = it.data?.data }
|
||||
getCaCert = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
uriToStream(applicationContext,it.data?.data){stream->
|
||||
caCert = stream.readBytes()
|
||||
if(caCert.size>5000){ Toast.makeText(applicationContext, R.string.file_too_large, Toast.LENGTH_SHORT).show(); caCert = byteArrayOf() }
|
||||
}
|
||||
}
|
||||
createManagedProfile = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {}
|
||||
addDeviceAdmin = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
val myDpm = applicationContext.getSystemService(DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
if(myDpm.isAdminActive(ComponentName(applicationContext, Receiver::class.java))){
|
||||
backToHome = true
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
registerActivityResult()
|
||||
registerActivityResult(this)
|
||||
setContent {
|
||||
OwnDroidTheme {
|
||||
MyScaffold()
|
||||
|
||||
@@ -51,6 +51,7 @@ class PackageInstallerReceiver:BroadcastReceiver(){
|
||||
else->R.string.unknown
|
||||
}
|
||||
Log.e("OwnDroid", intent.getIntExtra(EXTRA_STATUS,999).toString())
|
||||
if(toastText!=999){Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show()}
|
||||
val text = context.getString(R.string.app_installer_status) + context.getString(toastText)
|
||||
if(toastText!=999){Toast.makeText(context, text, Toast.LENGTH_SHORT).show()}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.*
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import com.bintianqi.owndroid.dpm.*
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
lateinit var getFile: ActivityResultLauncher<Intent>
|
||||
var fileUri: Uri? = null
|
||||
|
||||
fun uriToStream(
|
||||
context: Context,
|
||||
uri: Uri?,
|
||||
@@ -54,3 +60,23 @@ fun writeClipBoard(context: Context, string: String):Boolean{
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
fun registerActivityResult(context: ComponentActivity){
|
||||
getFile = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {activityResult ->
|
||||
activityResult.data.let {
|
||||
if(it==null){
|
||||
Toast.makeText(context.applicationContext, R.string.file_not_exist, Toast.LENGTH_SHORT).show()
|
||||
}else{
|
||||
fileUri = it.data
|
||||
}
|
||||
}
|
||||
}
|
||||
createManagedProfile = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {}
|
||||
addDeviceAdmin = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
val myDpm = context.applicationContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
if(myDpm.isAdminActive(ComponentName(context.applicationContext, Receiver::class.java))){
|
||||
backToHome = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,6 +229,9 @@ private fun Home(navCtrl:NavHostController, pkgName: String){
|
||||
SubPageItem(R.string.set_default_dialer,"",R.drawable.call_fill0){navCtrl.navigate("DefaultDialer")}
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 30.dp))
|
||||
LaunchedEffect(Unit) {
|
||||
fileUri = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,19 +813,19 @@ private fun InstallApp(){
|
||||
val installApkIntent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
installApkIntent.setType("application/vnd.android.package-archive")
|
||||
installApkIntent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
getApk.launch(installApkIntent)
|
||||
getFile.launch(installApkIntent)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.select_apk))
|
||||
}
|
||||
var selected by remember{mutableStateOf(false)}
|
||||
LaunchedEffect(selected){while(true){ delay(800); selected = apkUri!=null}}
|
||||
LaunchedEffect(selected){while(true){ delay(800); selected = fileUri!=null}}
|
||||
AnimatedVisibility(selected) {
|
||||
Spacer(Modifier.padding(vertical = 3.dp))
|
||||
Column(modifier = Modifier.fillMaxWidth()){
|
||||
Button(
|
||||
onClick = { uriToStream(myContext, apkUri){stream -> installPackage(myContext,stream)} },
|
||||
onClick = { uriToStream(myContext, fileUri){stream -> installPackage(myContext,stream)} },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.silent_install))
|
||||
@@ -830,7 +833,7 @@ private fun InstallApp(){
|
||||
Button(
|
||||
onClick = {
|
||||
val intent = Intent(Intent.ACTION_INSTALL_PACKAGE)
|
||||
intent.setData(apkUri)
|
||||
intent.setData(fileUri)
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
myContext.startActivity(intent)
|
||||
},
|
||||
|
||||
@@ -9,16 +9,9 @@ var selectedPackage = ""
|
||||
var applySelectedPackage = false
|
||||
var selectedPermission = ""
|
||||
var applySelectedPermission = false
|
||||
lateinit var getCaCert: ActivityResultLauncher<Intent>
|
||||
lateinit var createManagedProfile: ActivityResultLauncher<Intent>
|
||||
lateinit var getApk: ActivityResultLauncher<Intent>
|
||||
lateinit var getUserIcon: ActivityResultLauncher<Intent>
|
||||
lateinit var addDeviceAdmin: ActivityResultLauncher<Intent>
|
||||
|
||||
var userIconUri: Uri? = null
|
||||
var apkUri: Uri? = null
|
||||
var caCert = byteArrayOf()
|
||||
|
||||
fun isDeviceOwner(dpm: DevicePolicyManager): Boolean {
|
||||
return dpm.isDeviceOwnerApp("com.bintianqi.owndroid")
|
||||
}
|
||||
|
||||
@@ -321,8 +321,7 @@ fun DeviceInfo(){
|
||||
val encryptionStatus = mutableMapOf(
|
||||
DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE to stringResource(R.string.es_inactive),
|
||||
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE to stringResource(R.string.es_active),
|
||||
DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED to stringResource(R.string.es_unsupported),
|
||||
DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING to stringResource(R.string.unknown)
|
||||
DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED to stringResource(R.string.es_unsupported)
|
||||
)
|
||||
if(VERSION.SDK_INT>=23){ encryptionStatus[DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY] = stringResource(R.string.es_active_default_key) }
|
||||
if(VERSION.SDK_INT>=24){ encryptionStatus[DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER] = stringResource(R.string.es_active_per_user) }
|
||||
@@ -428,6 +427,8 @@ private fun SupportMsg(){
|
||||
focusMgr.clearFocus()
|
||||
myDpm.setShortSupportMessage(myComponent, shortMsg)
|
||||
myDpm.setLongSupportMessage(myComponent, longMsg)
|
||||
shortMsg = myDpm.getShortSupportMessage(myComponent)?.toString() ?: ""
|
||||
longMsg = myDpm.getLongSupportMessage(myComponent)?.toString() ?: ""
|
||||
Toast.makeText(myContext, R.string.success, Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
@@ -440,6 +441,8 @@ private fun SupportMsg(){
|
||||
focusMgr.clearFocus()
|
||||
myDpm.setShortSupportMessage(myComponent, null)
|
||||
myDpm.setLongSupportMessage(myComponent, null)
|
||||
shortMsg = myDpm.getShortSupportMessage(myComponent)?.toString() ?: ""
|
||||
longMsg = myDpm.getLongSupportMessage(myComponent)?.toString() ?: ""
|
||||
Toast.makeText(myContext, R.string.success, Toast.LENGTH_SHORT).show()
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
|
||||
@@ -41,9 +41,8 @@ import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.bintianqi.owndroid.*
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.Receiver
|
||||
import com.bintianqi.owndroid.toText
|
||||
import com.bintianqi.owndroid.ui.*
|
||||
import com.bintianqi.owndroid.ui.theme.bgColor
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -152,7 +151,7 @@ private fun Home(navCtrl: NavHostController,scrollState: ScrollState){
|
||||
}
|
||||
SubPageItem(R.string.wipe_data,"",R.drawable.warning_fill0){navCtrl.navigate("WipeData")}
|
||||
Spacer(Modifier.padding(vertical = 30.dp))
|
||||
LaunchedEffect(Unit){caCert =byteArrayOf()}
|
||||
LaunchedEffect(Unit){fileUri=null}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,34 +595,52 @@ private fun CaCert(){
|
||||
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
val myComponent = ComponentName(myContext,Receiver::class.java)
|
||||
var exist by remember{mutableStateOf(false)}
|
||||
var isEmpty by remember{mutableStateOf(true)}
|
||||
var uriPath by remember{mutableStateOf("")}
|
||||
var caCertByteArray = byteArrayOf()
|
||||
val refresh = {
|
||||
isEmpty = caCert.isEmpty()
|
||||
exist = if(!isEmpty){ myDpm.hasCaCertInstalled(myComponent, caCert) }else{ false }
|
||||
if(uriPath!=fileUri?.path){
|
||||
if(caCertByteArray.isEmpty()){
|
||||
uriToStream(myContext, fileUri){
|
||||
val array = it.readBytes()
|
||||
caCertByteArray = if(array.size<10000){
|
||||
array
|
||||
}else{
|
||||
byteArrayOf()
|
||||
}
|
||||
}
|
||||
exist = myDpm.hasCaCertInstalled(myComponent, caCertByteArray)
|
||||
}
|
||||
}
|
||||
}
|
||||
LaunchedEffect(exist){ while(true){ refresh();delay(600) } }
|
||||
LaunchedEffect(exist){ while(true){ refresh();delay(500) } }
|
||||
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
||||
Spacer(Modifier.padding(vertical = 10.dp))
|
||||
Text(text = stringResource(R.string.ca_cert), style = typography.headlineLarge)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Text(text = if(isEmpty){stringResource(R.string.please_select_ca_cert)}else{stringResource(R.string.cacert_installed, exist)}, modifier = Modifier.animateContentSize())
|
||||
AnimatedVisibility(uriPath!="") {
|
||||
Text(text = uriPath)
|
||||
}
|
||||
Text(
|
||||
text = if(uriPath==""){stringResource(R.string.please_select_ca_cert)}else{stringResource(R.string.cacert_installed, exist)},
|
||||
modifier = Modifier.animateContentSize()
|
||||
)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Button(
|
||||
onClick = {
|
||||
val caCertIntent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
caCertIntent.setType("*/*")
|
||||
caCertIntent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
getCaCert.launch(caCertIntent)
|
||||
getFile.launch(caCertIntent)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.select_ca_cert))
|
||||
}
|
||||
AnimatedVisibility(!isEmpty) {
|
||||
AnimatedVisibility(uriPath!="") {
|
||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
|
||||
Button(
|
||||
onClick = {
|
||||
val result = myDpm.installCaCert(myComponent, caCert)
|
||||
val result = myDpm.installCaCert(myComponent, caCertByteArray)
|
||||
Toast.makeText(myContext, if(result){R.string.success}else{R.string.fail}, Toast.LENGTH_SHORT).show()
|
||||
refresh()
|
||||
},
|
||||
@@ -634,8 +651,8 @@ private fun CaCert(){
|
||||
Button(
|
||||
onClick = {
|
||||
if(exist){
|
||||
myDpm.uninstallCaCert(myComponent, caCert)
|
||||
exist = myDpm.hasCaCertInstalled(myComponent, caCert)
|
||||
myDpm.uninstallCaCert(myComponent, caCertByteArray)
|
||||
exist = myDpm.hasCaCertInstalled(myComponent, caCertByteArray)
|
||||
Toast.makeText(myContext, if(exist){R.string.fail}else{R.string.success}, Toast.LENGTH_SHORT).show()
|
||||
}else{ Toast.makeText(myContext, R.string.not_exist, Toast.LENGTH_SHORT).show() }
|
||||
},
|
||||
|
||||
@@ -40,12 +40,10 @@ import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.bintianqi.owndroid.*
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.Receiver
|
||||
import com.bintianqi.owndroid.toText
|
||||
import com.bintianqi.owndroid.ui.*
|
||||
import com.bintianqi.owndroid.ui.theme.bgColor
|
||||
import com.bintianqi.owndroid.uriToStream
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
var affiliationID = mutableSetOf<String>()
|
||||
@@ -122,6 +120,9 @@ private fun Home(navCtrl: NavHostController,scrollState: ScrollState){
|
||||
SubPageItem(R.string.affiliation_id,"",R.drawable.id_card_fill0){navCtrl.navigate("AffiliationID")}
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 30.dp))
|
||||
LaunchedEffect(Unit) {
|
||||
fileUri = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,17 +510,17 @@ private fun UserIcon(){
|
||||
val intent = Intent(if(getContent){Intent.ACTION_GET_CONTENT}else{Intent.ACTION_PICK})
|
||||
if(getContent){intent.addCategory(Intent.CATEGORY_OPENABLE)}
|
||||
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
|
||||
getUserIcon.launch(intent)
|
||||
getFile.launch(intent)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.select_picture))
|
||||
}
|
||||
LaunchedEffect(Unit){ delay(600); canApply = userIconUri!=null }
|
||||
LaunchedEffect(Unit){ delay(600); canApply = fileUri!=null }
|
||||
AnimatedVisibility(canApply) {
|
||||
Button(
|
||||
onClick = {
|
||||
uriToStream(myContext, userIconUri){stream ->
|
||||
uriToStream(myContext, fileUri){stream ->
|
||||
val bitmap = BitmapFactory.decodeStream(stream)
|
||||
myDpm.setUserIcon(myComponent,bitmap)
|
||||
Toast.makeText(myContext, R.string.success, Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -14,7 +14,7 @@ object Animations{
|
||||
private val tween: FiniteAnimationSpec<IntOffset> = tween(450, easing = bezier)
|
||||
|
||||
val navHostEnterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
|
||||
fadeIn(tween(83, easing = LinearEasing)) +
|
||||
fadeIn(tween(150, easing = LinearEasing)) +
|
||||
slideIntoContainer(
|
||||
animationSpec = tween,
|
||||
towards = AnimatedContentTransitionScope.SlideDirection.End,
|
||||
|
||||
Reference in New Issue
Block a user