android: add option to change camera app id

This commit is contained in:
Kavish Devar
2025-10-01 01:24:28 +05:30
parent c7dc545ed4
commit b799cd1710
3 changed files with 135 additions and 3 deletions

View File

@@ -103,14 +103,18 @@ fun AppSettingsScreen(navController: NavController) {
val showResetDialog = remember { mutableStateOf(false) } val showResetDialog = remember { mutableStateOf(false) }
val showIrkDialog = remember { mutableStateOf(false) } val showIrkDialog = remember { mutableStateOf(false) }
val showEncKeyDialog = remember { mutableStateOf(false) } val showEncKeyDialog = remember { mutableStateOf(false) }
val showCameraDialog = remember { mutableStateOf(false) }
val irkValue = remember { mutableStateOf("") } val irkValue = remember { mutableStateOf("") }
val encKeyValue = remember { mutableStateOf("") } val encKeyValue = remember { mutableStateOf("") }
val cameraPackageValue = remember { mutableStateOf("") }
val irkError = remember { mutableStateOf<String?>(null) } val irkError = remember { mutableStateOf<String?>(null) }
val encKeyError = remember { mutableStateOf<String?>(null) } val encKeyError = remember { mutableStateOf<String?>(null) }
val cameraPackageError = remember { mutableStateOf<String?>(null) }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
val savedIrk = sharedPreferences.getString(AACPManager.Companion.ProximityKeyType.IRK.name, null) val savedIrk = sharedPreferences.getString(AACPManager.Companion.ProximityKeyType.IRK.name, null)
val savedEncKey = sharedPreferences.getString(AACPManager.Companion.ProximityKeyType.ENC_KEY.name, null) val savedEncKey = sharedPreferences.getString(AACPManager.Companion.ProximityKeyType.ENC_KEY.name, null)
val savedCameraPackage = sharedPreferences.getString("custom_camera_package", null)
if (savedIrk != null) { if (savedIrk != null) {
try { try {
@@ -131,6 +135,9 @@ fun AppSettingsScreen(navController: NavController) {
e.printStackTrace() e.printStackTrace()
} }
} }
if (savedCameraPackage != null) {
cameraPackageValue.value = savedCameraPackage
}
} }
val showPhoneBatteryInWidget = remember { val showPhoneBatteryInWidget = remember {
@@ -292,6 +299,18 @@ fun AppSettingsScreen(navController: NavController) {
independent = true independent = true
) )
Spacer(modifier = Modifier.height(16.dp))
NavigationButton(
to = "",
title = stringResource(R.string.camera_control),
name = stringResource(R.string.set_custom_camera_package),
navController = navController,
onClick = { showCameraDialog.value = true },
independent = true,
description = stringResource(R.string.camera_control_app_description)
)
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
StyledToggle( StyledToggle(
@@ -877,6 +896,86 @@ fun AppSettingsScreen(navController: NavController) {
} }
) )
} }
if (showCameraDialog.value) {
AlertDialog(
onDismissRequest = { showCameraDialog.value = false },
title = {
Text(
stringResource(R.string.set_custom_camera_package),
fontFamily = FontFamily(Font(R.font.sf_pro)),
fontWeight = FontWeight.Medium
)
},
text = {
Column {
Text(
stringResource(R.string.enter_custom_camera_package),
fontFamily = FontFamily(Font(R.font.sf_pro)),
modifier = Modifier.padding(bottom = 8.dp)
)
OutlinedTextField(
value = cameraPackageValue.value,
onValueChange = {
cameraPackageValue.value = it
cameraPackageError.value = null
},
modifier = Modifier.fillMaxWidth(),
isError = cameraPackageError.value != null,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Ascii,
capitalization = KeyboardCapitalization.None
),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = if (isDarkTheme) Color(0xFF007AFF) else Color(0xFF3C6DF5),
unfocusedBorderColor = if (isDarkTheme) Color.Gray else Color.LightGray
),
supportingText = {
if (cameraPackageError.value != null) {
Text(cameraPackageError.value!!, color = MaterialTheme.colorScheme.error)
}
},
label = { Text(stringResource(R.string.custom_camera_package)) }
)
}
},
confirmButton = {
val successText = stringResource(R.string.custom_camera_package_set_success)
TextButton(
onClick = {
if (cameraPackageValue.value.isBlank()) {
sharedPreferences.edit { remove("custom_camera_package") }
Toast.makeText(context, successText, Toast.LENGTH_SHORT).show()
showCameraDialog.value = false
return@TextButton
}
sharedPreferences.edit { putString("custom_camera_package", cameraPackageValue.value) }
Toast.makeText(context, successText, Toast.LENGTH_SHORT).show()
showCameraDialog.value = false
}
) {
Text(
"Save",
fontFamily = FontFamily(Font(R.font.sf_pro)),
fontWeight = FontWeight.Medium
)
}
},
dismissButton = {
TextButton(
onClick = { showCameraDialog.value = false }
) {
Text(
"Cancel",
fontFamily = FontFamily(Font(R.font.sf_pro)),
fontWeight = FontWeight.Medium
)
}
}
)
}
} }
} }
} }

View File

@@ -28,19 +28,47 @@ import kotlin.io.encoding.ExperimentalEncodingApi
private const val TAG="AppListenerService" private const val TAG="AppListenerService"
val cameraPackages = setOf( val cameraPackages = mutableSetOf(
"com.google.android.GoogleCamera", "com.google.android.GoogleCamera",
"com.sec.android.app.camera", "com.sec.android.app.camera",
"com.android.camera", "com.android.camera",
"com.oppo.camera", "com.oppo.camera",
"com.motorola.camera2", "com.motorola.camera2",
"org.codeaurora.snapcam", "org.codeaurora.snapcam"
"com.nothing.camera"
) )
var cameraOpen = false var cameraOpen = false
private var currentCustomPackage: String? = null
class AppListenerService : AccessibilityService() { class AppListenerService : AccessibilityService() {
private lateinit var prefs: android.content.SharedPreferences
private val preferenceChangeListener = android.content.SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
if (key == "custom_camera_package") {
val newPackage = sharedPreferences.getString(key, null)
currentCustomPackage?.let { cameraPackages.remove(it) }
if (newPackage != null && newPackage.isNotBlank()) {
cameraPackages.add(newPackage)
}
currentCustomPackage = newPackage
}
}
override fun onCreate() {
super.onCreate()
prefs = getSharedPreferences("settings", MODE_PRIVATE)
val customPackage = prefs.getString("custom_camera_package", null)
if (customPackage != null && customPackage.isNotBlank()) {
cameraPackages.add(customPackage)
currentCustomPackage = customPackage
}
prefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
}
override fun onDestroy() {
super.onDestroy()
prefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
}
override fun onAccessibilityEvent(ev: AccessibilityEvent?) { override fun onAccessibilityEvent(ev: AccessibilityEvent?) {
try { try {
if (ev?.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { if (ev?.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {

View File

@@ -177,6 +177,11 @@
<string name="camera_remote">Camera Remote</string> <string name="camera_remote">Camera Remote</string>
<string name="camera_control">Camera Control</string> <string name="camera_control">Camera Control</string>
<string name="camera_control_description">Capture a photo, start or stop recording, and more using either Press Once or Press and Hold. When using AirPods for camera actions, if you select Press Once, media control gestures will be unavailable, and if you select Press and Hold, listening mode and Digital Assistant gestures will be unavailable.</string> <string name="camera_control_description">Capture a photo, start or stop recording, and more using either Press Once or Press and Hold. When using AirPods for camera actions, if you select Press Once, media control gestures will be unavailable, and if you select Press and Hold, listening mode and Digital Assistant gestures will be unavailable.</string>
<string name="camera_control_app_description">Set a custom app package for camera detection</string>
<string name="set_custom_camera_package">Set Custom Camera appid</string>
<string name="enter_custom_camera_package">Enter the application id of the camera app:</string>
<string name="custom_camera_package">Custom Camera appid</string>
<string name="custom_camera_package_set_success">Custom camera appid set successfully</string>
<string name="app_listener_service_label">Camera listener</string> <string name="app_listener_service_label">Camera listener</string>
<string name="app_listener_service_description">Listener service for LibrePods to detect when the camera is active to activate camera control on AirPods.</string> <string name="app_listener_service_description">Listener service for LibrePods to detect when the camera is active to activate camera control on AirPods.</string>
</resources> </resources>