Add shortcuts to lock screen, disable camera or mute

This commit is contained in:
BinTianqi
2025-04-20 10:54:08 +08:00
parent a30a9abb3c
commit 19acf94e7b
8 changed files with 109 additions and 24 deletions

View File

@@ -44,6 +44,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.core.content.edit
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.net.toUri
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bintianqi.owndroid.ui.FunctionItem
@@ -85,13 +86,22 @@ fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
@Composable
fun SettingsOptionsScreen(onNavigateUp: () -> Unit) {
val sp = SharedPrefs(LocalContext.current)
val context = LocalContext.current
val sp = SharedPrefs(context)
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
SwitchItem(
R.string.show_dangerous_features, icon = R.drawable.warning_fill0,
getState = { sp.displayDangerousFeatures },
onCheckedChange = { sp.displayDangerousFeatures = it }
)
SwitchItem(
R.string.shortcuts, icon = R.drawable.open_in_new,
getState = { sp.shortcuts }, onCheckedChange = {
sp.shortcuts = it
ShortcutManagerCompat.removeAllDynamicShortcuts(context)
createShortcuts(context)
}
)
}
}

View File

@@ -22,6 +22,7 @@ class SharedPrefs(context: Context) {
var lockPasswordHash by StringSharedPref("lock.password.sha256")
var biometricsUnlock by BooleanSharedPref("lock.biometrics")
var applicationsListView by BooleanSharedPref("applications.list_view", true)
var shortcuts by BooleanSharedPref("shortcuts", true)
}
private class BooleanSharedPref(val key: String, val defValue: Boolean = false): ReadWriteProperty<SharedPrefs, Boolean> {

View File

@@ -1,17 +1,72 @@
package com.bintianqi.owndroid
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import com.bintianqi.owndroid.dpm.getDPM
import com.bintianqi.owndroid.dpm.getReceiver
class ShortcutsReceiverActivity: Activity() {
class ShortcutsReceiverActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
if(intent.action == "com.bintianqi.owndroid.action.LOCK") {
getDPM().lockNow()
val action = intent.action?.removePrefix("com.bintianqi.owndroid.action.")
if (action != null && SharedPrefs(this).shortcuts) {
val dpm = getDPM()
val receiver = getReceiver()
when (action) {
"LOCK" -> dpm.lockNow()
"DISABLE_CAMERA" -> {
dpm.setCameraDisabled(receiver, !dpm.getCameraDisabled(receiver))
createShortcuts(this)
}
} catch(_: Exception) {}
"MUTE" -> {
dpm.setMasterVolumeMuted(receiver, !dpm.isMasterVolumeMuted(receiver))
createShortcuts(this)
}
}
}
} finally {
finish()
}
}
}
fun createShortcuts(context: Context) {
if (!SharedPrefs(context).shortcuts) return
val action = "com.bintianqi.owndroid.action"
val baseIntent = Intent(context, ShortcutsReceiverActivity::class.java)
val dpm = context.getDPM()
val receiver = context.getReceiver()
val cameraDisabled = dpm.getCameraDisabled(receiver)
val muted = dpm.isMasterVolumeMuted(receiver)
val list = listOf(
ShortcutInfoCompat.Builder(context, "LOCK")
.setIcon(IconCompat.createWithResource(context, R.drawable.screen_lock_portrait_fill0))
.setShortLabel(context.getString(R.string.lock_screen))
.setIntent(Intent(baseIntent).setAction("$action.LOCK")),
ShortcutInfoCompat.Builder(context, "DISABLE_CAMERA")
.setIcon(
IconCompat.createWithResource(
context,
if (cameraDisabled) R.drawable.photo_camera_fill0 else R.drawable.no_photography_fill0
)
)
.setShortLabel(context.getString(if (cameraDisabled) R.string.enable_camera else R.string.disable_cam))
.setIntent(Intent(baseIntent).setAction("$action.DISABLE_CAMERA")),
ShortcutInfoCompat.Builder(context, "MUTE")
.setIcon(
IconCompat.createWithResource(
context,
if (muted) R.drawable.volume_up_fill0 else R.drawable.volume_off_fill0
)
)
.setShortLabel(context.getString(if (muted) R.string.unmute else R.string.mute))
.setIntent(Intent(baseIntent).setAction("$action.MUTE"))
)
ShortcutManagerCompat.setDynamicShortcuts(context, list.map { it.build() })
}

View File

@@ -22,12 +22,14 @@ import android.util.Log
import androidx.annotation.DrawableRes
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.toBitmap
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.Receiver
import com.bintianqi.owndroid.SharedPrefs
import com.bintianqi.owndroid.ShortcutsReceiverActivity
import com.bintianqi.owndroid.backToHomeStateFlow
import com.bintianqi.owndroid.createShortcuts
import com.bintianqi.owndroid.myPrivilege
import com.rosan.dhizuku.api.Dhizuku
import com.rosan.dhizuku.api.Dhizuku.binderWrapper
@@ -520,26 +522,17 @@ fun parsePackageInstallerMessage(context: Context, result: Intent): String {
fun handlePrivilegeChange(context: Context) {
val privilege = myPrivilege.value
val activated = privilege.device || privilege.profile
val sp = SharedPrefs(context)
if(activated) {
createShortcuts(context)
if(!privilege.dhizuku) {
setDefaultAffiliationID(context)
if(VERSION.SDK_INT >= 25) {
val sm = context.getSystemService(ShortcutManager::class.java)
val lockIntent = Intent("com.bintianqi.owndroid.action.LOCK")
.setComponent(ComponentName(context, ShortcutsReceiverActivity::class.java))
val shortcut = ShortcutInfo.Builder(context, "LockScreen")
.setShortLabel(context.getString(R.string.lock_now))
.setIcon(Icon.createWithBitmap(context.getDrawable(R.drawable.screen_lock_portrait_fill0)?.toBitmap()))
.setIntent(lockIntent)
sm.addDynamicShortcuts(listOf(shortcut.build()))
}
}
} else {
SharedPrefs(context).isDefaultAffiliationIdSet = false
sp.isDefaultAffiliationIdSet = false
if(VERSION.SDK_INT >= 25) {
val sm = context.getSystemService(ShortcutManager::class.java)
sm.removeDynamicShortcuts(listOf("LockScreen"))
ShortcutManagerCompat.removeAllDynamicShortcuts(context)
}
SharedPrefs(context).isApiEnabled = false
sp.isApiEnabled = false
}
}

View File

@@ -122,6 +122,7 @@ import com.bintianqi.owndroid.HorizontalPadding
import com.bintianqi.owndroid.NotificationUtils
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.SharedPrefs
import com.bintianqi.owndroid.createShortcuts
import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.myPrivilege
@@ -250,8 +251,11 @@ fun SystemOptionsScreen(onNavigateUp: () -> Unit) {
val privilege by myPrivilege.collectAsStateWithLifecycle()
var dialog by remember { mutableIntStateOf(0) }
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
SwitchItem(R.string.disable_cam, icon = R.drawable.photo_camera_fill0,
getState = { dpm.getCameraDisabled(null) }, onCheckedChange = { dpm.setCameraDisabled(receiver,it) }
SwitchItem(R.string.disable_cam, icon = R.drawable.no_photography_fill0,
getState = { dpm.getCameraDisabled(null) }, onCheckedChange = {
dpm.setCameraDisabled(receiver, it)
createShortcuts(context)
}
)
SwitchItem(R.string.disable_screen_capture, icon = R.drawable.screenshot_fill0,
getState = { dpm.getScreenCaptureDisabled(null) }, onCheckedChange = { dpm.setScreenCaptureDisabled(receiver,it) }
@@ -275,7 +279,10 @@ fun SystemOptionsScreen(onNavigateUp: () -> Unit) {
}
}
SwitchItem(R.string.master_mute, icon = R.drawable.volume_off_fill0,
getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = { dpm.setMasterVolumeMuted(receiver,it) }
getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = {
dpm.setMasterVolumeMuted(receiver,it)
createShortcuts(context)
}
)
if(VERSION.SDK_INT >= 26) {
SwitchItem(R.string.backup_service, icon = R.drawable.backup_fill0,

View 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="m880,765 l-80,-80v-405L638,280l-73,-80L395,200l-38,42 -57,-57 60,-65h240l74,80h126q33,0 56.5,23.5T880,280v485ZM160,840q-33,0 -56.5,-23.5T80,760v-480q0,-33 23.5,-56.5T160,200h41l80,80L160,280v480h601l80,80L160,840ZM626,625q-25,34 -62.5,54.5T480,700q-75,0 -127.5,-52.5T300,520q0,-46 20.5,-83.5T375,374l58,58q-24,13 -38.5,36T380,520q0,42 29,71t71,29q29,0 52,-14.5t36,-38.5l58,58ZM608,392q25,24 38.5,57t13.5,71v12q0,6 -1,12L456,341q6,-1 12,-1h12q38,0 71,13.5t57,38.5ZM819,932 L27,140l57,-57L876,875l-57,57ZM407,520ZM578,463Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -117,18 +117,22 @@
<!--System-->
<string name="system">系统</string>
<string name="disable_cam">禁用相机</string>
<string name="enable_camera">启用相机</string>
<string name="disable_screen_capture">禁止屏幕捕获</string>
<string name="disable_status_bar">禁用状态栏</string>
<string name="auto_time">自动设置时间</string>
<string name="auto_timezone">自动设置时区</string>
<string name="require_auto_time">要求自动时间</string>
<string name="master_mute">全局静音</string>
<string name="mute">静音</string>
<string name="unmute">取消静音</string>
<string name="backup_service">备份服务</string>
<string name="disable_bt_contact_share">禁止蓝牙分享联系人</string>
<string name="common_criteria_mode">通用标准模式</string>
<string name="disable_usb_signal">禁用USB信号</string>
<string name="keyguard">锁屏</string>
<string name="lock_now">立即锁屏</string>
<string name="lock_screen">锁屏</string>
<string name="evict_credential_encryption_key">移除凭证加密密钥</string>
<string name="hardware_monitor">硬件监视器</string>
<string name="refresh_interval">刷新间隔</string>
@@ -551,6 +555,7 @@
<string name="project_homepage">项目主页</string>
<string name="appearance">外观</string>
<string name="shortcuts">快捷方式</string>
<string name="app_lock">应用锁</string>
<string name="minimum_length_4">长度不得小于4</string>
<string name="leave_empty_to_remain_unchanged">留空以保持未更改</string>

View File

@@ -126,18 +126,22 @@
<!--System-->
<string name="system">System</string>
<string name="disable_cam">Disable camera</string>
<string name="enable_camera">Enable camera</string>
<string name="disable_screen_capture">Disable screen capture</string>
<string name="disable_status_bar">Disable status bar</string>
<string name="auto_time">Auto time</string>
<string name="require_auto_time">Require auto time</string>
<string name="auto_timezone">Auto timezone</string>
<string name="master_mute">Master volume mute</string>
<string name="mute">Mute</string>
<string name="unmute">Unmute</string>
<string name="backup_service">Backup service</string>
<string name="disable_bt_contact_share">Disable bluetooth contact sharing</string>
<string name="common_criteria_mode">Common criteria mode</string>
<string name="disable_usb_signal">Disable USB signal</string>
<string name="keyguard">Keyguard</string>
<string name="lock_now">Lock screen now</string>
<string name="lock_screen">Lock screen</string>
<string name="evict_credential_encryption_key">Evict credential encryption key</string>
<string name="hardware_monitor">Hardware monitor</string>
<string name="refresh_interval">Refresh interval</string>
@@ -584,6 +588,7 @@
<string name="project_homepage">Project homepage</string>
<string name="appearance">Appearance</string>
<string name="shortcuts">Shortcuts</string>
<string name="app_lock">App lock</string>
<string name="minimum_length_4">The length must not be less than 4</string>
<string name="leave_empty_to_remain_unchanged">Leave empty to remain unchanged</string>