fix for pre-tiramisu android versions

This commit is contained in:
Kavish Devar
2025-01-07 23:22:16 +05:30
parent c6863a8d2c
commit fda343ca39
8 changed files with 135 additions and 38 deletions

View File

@@ -18,6 +18,7 @@
package me.kavishdevar.aln package me.kavishdevar.aln
import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothDevice.TRANSPORT_LE import android.bluetooth.BluetoothDevice.TRANSPORT_LE
@@ -25,11 +26,13 @@ import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -49,7 +52,7 @@ import org.lsposed.hiddenapibypass.HiddenApiBypass
import java.util.UUID import java.util.UUID
class CustomDevice : ComponentActivity() { class CustomDevice : ComponentActivity() {
@SuppressLint("MissingPermission", "CoroutineCreationDuringComposition", "NewApi") @SuppressLint("MissingPermission", "CoroutineCreationDuringComposition")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
@@ -152,7 +155,7 @@ class CustomDevice : ComponentActivity() {
} }
} }
@SuppressLint("MissingPermission", "NewApi") @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
fun sendWriteRequest( fun sendWriteRequest(
gatt: BluetoothGatt, gatt: BluetoothGatt,
characteristicUuid: String, characteristicUuid: String,
@@ -177,6 +180,10 @@ fun sendWriteRequest(
// Send the write request // Send the write request
val success = gatt.writeCharacteristic(characteristic, value, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) val success = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
gatt.writeCharacteristic(characteristic, value, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
} else {
gatt.writeCharacteristic(characteristic)
}
Log.d("GATT", "Write request sent $success to UUID: $characteristicUuid") Log.d("GATT", "Write request sent $success to UUID: $characteristicUuid")
} }

View File

@@ -22,9 +22,11 @@ import android.annotation.SuppressLint
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Context.RECEIVER_EXPORTED
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.ServiceConnection import android.content.ServiceConnection
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
@@ -110,7 +112,7 @@ class MainActivity : ComponentActivity() {
} }
} }
@SuppressLint("MissingPermission", "InlinedApi") @SuppressLint("MissingPermission", "InlinedApi", "UnspecifiedRegisterReceiverFlag")
@OptIn(ExperimentalPermissionsApi::class) @OptIn(ExperimentalPermissionsApi::class)
@Composable @Composable
fun Main() { fun Main() {
@@ -146,7 +148,12 @@ fun Main() {
addAction(AirPodsNotifications.AIRPODS_CONNECTION_DETECTED) addAction(AirPodsNotifications.AIRPODS_CONNECTION_DETECTED)
} }
Log.d("MainActivity", "Registering Receiver") Log.d("MainActivity", "Registering Receiver")
context.registerReceiver(connectionStatusReceiver, filter, Context.RECEIVER_EXPORTED)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
context.registerReceiver(connectionStatusReceiver, filter, RECEIVER_EXPORTED)
} else {
context.registerReceiver(connectionStatusReceiver, filter)
}
Log.d("MainActivity", "Registered Receiver") Log.d("MainActivity", "Registered Receiver")
NavHost( NavHost(

View File

@@ -23,20 +23,29 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.Build import android.os.Build
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -50,19 +59,36 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import me.kavishdevar.aln.R import me.kavishdevar.aln.R
import me.kavishdevar.aln.services.AirPodsService import me.kavishdevar.aln.services.AirPodsService
import me.kavishdevar.aln.utils.AirPodsNotifications import me.kavishdevar.aln.utils.AirPodsNotifications
import me.kavishdevar.aln.utils.NoiseControlMode import me.kavishdevar.aln.utils.NoiseControlMode
import kotlin.math.roundToInt
@SuppressLint("UnspecifiedRegisterReceiverFlag") @SuppressLint("UnspecifiedRegisterReceiverFlag")
@Composable @Composable
fun NoiseControlSettings(service: AirPodsService) { fun NoiseControlSettings(service: AirPodsService) {
val context = LocalContext.current val context = LocalContext.current
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val offListeningMode = sharedPreferences.getBoolean("off_listening_mode", true) val offListeningMode = remember { mutableStateOf(sharedPreferences.getBoolean("off_listening_mode", true)) }
val preferenceChangeListener = remember {
SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
if (key == "off_listening_mode") {
offListeningMode.value = sharedPreferences.getBoolean("off_listening_mode", true)
}
}
}
DisposableEffect(Unit) {
sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
onDispose {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
}
}
val isDarkTheme = isSystemInDarkTheme() val isDarkTheme = isSystemInDarkTheme()
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFE3E3E8) val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFE3E3E8)
@@ -71,18 +97,28 @@ fun NoiseControlSettings(service: AirPodsService) {
val selectedBackground = if (isDarkTheme) Color(0xFF5C5A5F) else Color(0xFFFFFFFF) val selectedBackground = if (isDarkTheme) Color(0xFF5C5A5F) else Color(0xFFFFFFFF)
val noiseControlMode = remember { mutableStateOf(NoiseControlMode.OFF) } val noiseControlMode = remember { mutableStateOf(NoiseControlMode.OFF) }
val selectedOffset = remember { mutableFloatStateOf(0f) }
val animatedOffset = animateFloatAsState(targetValue = selectedOffset.floatValue)
val d1a = remember { mutableFloatStateOf(0f) } val d1a = remember { mutableFloatStateOf(0f) }
val d2a = remember { mutableFloatStateOf(0f) } val d2a = remember { mutableFloatStateOf(0f) }
val d3a = remember { mutableFloatStateOf(0f) } val d3a = remember { mutableFloatStateOf(0f) }
val boxWidth = 200.dp.value
fun onModeSelected(mode: NoiseControlMode, received: Boolean = false) { fun onModeSelected(mode: NoiseControlMode, received: Boolean = false) {
if (!received && !offListeningMode && mode == NoiseControlMode.OFF) { if (!received && !offListeningMode.value && mode == NoiseControlMode.OFF) {
noiseControlMode.value = NoiseControlMode.ADAPTIVE noiseControlMode.value = NoiseControlMode.ADAPTIVE
} else { } else {
noiseControlMode.value = mode noiseControlMode.value = mode
} }
if (!received) service.setANCMode(mode.ordinal + 1) if (!received) service.setANCMode(mode.ordinal + 1)
selectedOffset.floatValue = when (noiseControlMode.value) {
NoiseControlMode.NOISE_CANCELLATION -> 3 * boxWidth
NoiseControlMode.OFF -> 0f
NoiseControlMode.ADAPTIVE -> 2 * boxWidth
NoiseControlMode.TRANSPARENCY -> 1 * boxWidth
}
when (noiseControlMode.value) { when (noiseControlMode.value) {
NoiseControlMode.NOISE_CANCELLATION -> { NoiseControlMode.NOISE_CANCELLATION -> {
d1a.floatValue = 1f d1a.floatValue = 1f
@@ -107,6 +143,15 @@ fun NoiseControlSettings(service: AirPodsService) {
} }
} }
LaunchedEffect(noiseControlMode.value) {
selectedOffset.value = when (noiseControlMode.value) {
NoiseControlMode.NOISE_CANCELLATION -> 3 * boxWidth
NoiseControlMode.OFF -> 0f
NoiseControlMode.ADAPTIVE -> 2 * boxWidth
NoiseControlMode.TRANSPARENCY -> 1 * boxWidth
}
}
val noiseControlReceiver = remember { val noiseControlReceiver = remember {
object : BroadcastReceiver() { object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@@ -154,13 +199,26 @@ fun NoiseControlSettings(service: AirPodsService) {
.fillMaxWidth() .fillMaxWidth()
.height(75.dp) .height(75.dp)
.padding(8.dp) .padding(8.dp)
.draggable(
orientation = Orientation.Horizontal,
state = rememberDraggableState { delta ->
selectedOffset.floatValue = (selectedOffset.floatValue + delta).coerceIn(0f, 3 * boxWidth)
}
)
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(backgroundColor, RoundedCornerShape(14.dp)) .background(backgroundColor, RoundedCornerShape(14.dp))
) { ) {
if (offListeningMode) { Box(
modifier = Modifier
.offset { IntOffset(animatedOffset.value.roundToInt(), 0) }
.width(boxWidth.dp)
.height(75.dp)
.background(selectedBackground, RoundedCornerShape(14.dp))
)
if (offListeningMode.value) {
NoiseControlButton( NoiseControlButton(
icon = ImageBitmap.imageResource(R.drawable.noise_cancellation), icon = ImageBitmap.imageResource(R.drawable.noise_cancellation),
onClick = { onModeSelected(NoiseControlMode.OFF) }, onClick = { onModeSelected(NoiseControlMode.OFF) },
@@ -219,7 +277,7 @@ fun NoiseControlSettings(service: AirPodsService) {
.padding(horizontal = 8.dp) .padding(horizontal = 8.dp)
.padding(top = 1.dp) .padding(top = 1.dp)
) { ) {
if (offListeningMode) { if (offListeningMode.value) {
Text( Text(
text = "Off", text = "Off",
style = TextStyle(fontSize = 12.sp, color = textColor), style = TextStyle(fontSize = 12.sp, color = textColor),

View File

@@ -86,7 +86,7 @@ import me.kavishdevar.aln.ui.theme.ALNTheme
import me.kavishdevar.aln.utils.AirPodsNotifications import me.kavishdevar.aln.utils.AirPodsNotifications
@OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class)
@SuppressLint("MissingPermission", "NewApi") @SuppressLint("MissingPermission")
@Composable @Composable
fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService, fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
navController: NavController, isConnected: Boolean) { navController: NavController, isConnected: Boolean) {

View File

@@ -88,7 +88,7 @@ import me.kavishdevar.aln.services.AirPodsService
import me.kavishdevar.aln.utils.AirPodsNotifications import me.kavishdevar.aln.utils.AirPodsNotifications
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "UnspecifiedRegisterReceiverFlag")
@Composable @Composable
fun DebugScreen(navController: NavController) { fun DebugScreen(navController: NavController) {
val hazeState = remember { HazeState() } val hazeState = remember { HazeState() }
@@ -158,6 +158,8 @@ fun DebugScreen(navController: NavController) {
val intentFilter = IntentFilter(AirPodsNotifications.Companion.AIRPODS_DATA) val intentFilter = IntentFilter(AirPodsNotifications.Companion.AIRPODS_DATA)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.registerReceiver(receiver, intentFilter, Context.RECEIVER_EXPORTED) context.registerReceiver(receiver, intentFilter, Context.RECEIVER_EXPORTED)
} else {
context.registerReceiver(receiver, intentFilter)
} }
} }

View File

@@ -23,6 +23,7 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Build
import android.service.quicksettings.Tile import android.service.quicksettings.Tile
import android.service.quicksettings.TileService import android.service.quicksettings.TileService
import android.util.Log import android.util.Log
@@ -35,7 +36,7 @@ class AirPodsQSService: TileService() {
private lateinit var ancStatusReceiver: BroadcastReceiver private lateinit var ancStatusReceiver: BroadcastReceiver
private lateinit var availabilityReceiver: BroadcastReceiver private lateinit var availabilityReceiver: BroadcastReceiver
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi", "UnspecifiedRegisterReceiverFlag")
override fun onStartListening() { override fun onStartListening() {
super.onStartListening() super.onStartListening()
currentModeIndex = (ServiceManager.getService()?.getANC()?.minus(1)) ?: -1 currentModeIndex = (ServiceManager.getService()?.getANC()?.minus(1)) ?: -1
@@ -77,9 +78,17 @@ class AirPodsQSService: TileService() {
} }
} }
registerReceiver(ancStatusReceiver, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
IntentFilter(AirPodsNotifications.Companion.ANC_DATA), RECEIVER_EXPORTED) registerReceiver(
ancStatusReceiver,
IntentFilter(AirPodsNotifications.Companion.ANC_DATA), RECEIVER_EXPORTED
)
} else {
registerReceiver(
ancStatusReceiver,
IntentFilter(AirPodsNotifications.Companion.ANC_DATA)
)
}
qsTile.state = if (ServiceManager.getService()?.isConnected == true) Tile.STATE_ACTIVE else Tile.STATE_UNAVAILABLE qsTile.state = if (ServiceManager.getService()?.isConnected == true) Tile.STATE_ACTIVE else Tile.STATE_UNAVAILABLE
val ancIndex = ServiceManager.getService()?.getANC() val ancIndex = ServiceManager.getService()?.getANC()
currentModeIndex = if (ancIndex != null) { if (ancIndex == 2) 0 else if (ancIndex == 3) 1 else if (ancIndex == 4) 2 else 2 } else 0 currentModeIndex = if (ancIndex != null) { if (ancIndex == 2) 0 else if (ancIndex == 3) 1 else if (ancIndex == 4) 2 else 2 } else 0

View File

@@ -107,10 +107,14 @@ class AirPodsService: Service() {
@Suppress("ClassName") @Suppress("ClassName")
private object bluetoothReceiver: BroadcastReceiver() { private object bluetoothReceiver: BroadcastReceiver() {
@SuppressLint("NewApi", "MissingPermission") @SuppressLint("MissingPermission")
override fun onReceive(context: Context?, intent: Intent) { override fun onReceive(context: Context?, intent: Intent) {
val bluetoothDevice = val bluetoothDevice =
intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE", BluetoothDevice::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE", BluetoothDevice::class.java)
} else {
intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE") as BluetoothDevice?
}
val action = intent.action val action = intent.action
val context = context?.applicationContext val context = context?.applicationContext
val name = context?.getSharedPreferences("settings", MODE_PRIVATE)?.getString("name", bluetoothDevice?.name) val name = context?.getSharedPreferences("settings", MODE_PRIVATE)?.getString("name", bluetoothDevice?.name)
@@ -148,7 +152,7 @@ class AirPodsService: Service() {
notificationManager.createNotificationChannel(notificationChannel) notificationManager.createNotificationChannel(notificationChannel)
val notification = NotificationCompat.Builder(this, "background_service_status") val notification = NotificationCompat.Builder(this, "background_service_status")
.setSmallIcon(R.drawable.airpods) .setSmallIcon(R.drawable.airpods)
.setContentTitle("AirPods are not connected") .setContentTitle("AirPods not connected")
.setCategory(Notification.CATEGORY_SERVICE) .setCategory(Notification.CATEGORY_SERVICE)
.setPriority(NotificationCompat.PRIORITY_LOW) .setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true) .setOngoing(true)
@@ -261,24 +265,24 @@ class AirPodsService: Service() {
updatedNotification = NotificationCompat.Builder(this, "background_service_status") updatedNotification = NotificationCompat.Builder(this, "background_service_status")
.setSmallIcon(R.drawable.airpods) .setSmallIcon(R.drawable.airpods)
.setContentTitle("""AirPods ${batteryList?.find { it.component == BatteryComponent.LEFT }?.let { .setContentTitle("""$airpodsName ${batteryList?.find { it.component == BatteryComponent.LEFT }?.let {
// if (it.status != BatteryStatus.DISCONNECTED) { if (it.status != BatteryStatus.DISCONNECTED) {
" L:${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%" " L:${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%"
// } else { } else {
// "" ""
// } }
} ?: ""}${batteryList?.find { it.component == BatteryComponent.RIGHT }?.let { } ?: ""}${batteryList?.find { it.component == BatteryComponent.RIGHT }?.let {
// if (it.status != BatteryStatus.DISCONNECTED) { if (it.status != BatteryStatus.DISCONNECTED) {
" R:${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%" " R:${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%"
// } else { } else {
// "" ""
// } }
} ?: ""}${batteryList?.find { it.component == BatteryComponent.CASE }?.let { } ?: ""}${batteryList?.find { it.component == BatteryComponent.CASE }?.let {
// if (it.status != BatteryStatus.DISCONNECTED) { if (it.status != BatteryStatus.DISCONNECTED) {
" C:${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%" " C:${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%"
// } else { } else {
// "" ""
// } }
} ?: ""}""") } ?: ""}""")
.setCategory(Notification.CATEGORY_SERVICE) .setCategory(Notification.CATEGORY_SERVICE)
.setPriority(NotificationCompat.PRIORITY_LOW) .setPriority(NotificationCompat.PRIORITY_LOW)
@@ -288,7 +292,7 @@ class AirPodsService: Service() {
} else { } else {
updatedNotification = NotificationCompat.Builder(this, "background_service_status") updatedNotification = NotificationCompat.Builder(this, "background_service_status")
.setSmallIcon(R.drawable.airpods) .setSmallIcon(R.drawable.airpods)
.setContentTitle("AirPods are not connected") .setContentTitle("AirPods not connected")
.setCategory(Notification.CATEGORY_SERVICE) .setCategory(Notification.CATEGORY_SERVICE)
.setPriority(NotificationCompat.PRIORITY_LOW) .setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true) .setOngoing(true)
@@ -301,7 +305,7 @@ class AirPodsService: Service() {
private lateinit var connectionReceiver: BroadcastReceiver private lateinit var connectionReceiver: BroadcastReceiver
private lateinit var disconnectionReceiver: BroadcastReceiver private lateinit var disconnectionReceiver: BroadcastReceiver
@SuppressLint("InlinedApi", "MissingPermission") @SuppressLint("InlinedApi", "MissingPermission", "UnspecifiedRegisterReceiverFlag")
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("AirPodsService", "Service started") Log.d("AirPodsService", "Service started")
ServiceManager.setService(this) ServiceManager.setService(this)
@@ -319,12 +323,20 @@ class AirPodsService: Service() {
addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED") addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED")
} }
registerReceiver(bluetoothReceiver, serviceIntentFilter, RECEIVER_EXPORTED) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(bluetoothReceiver, serviceIntentFilter, RECEIVER_EXPORTED)
} else {
registerReceiver(bluetoothReceiver, serviceIntentFilter)
}
connectionReceiver = object: BroadcastReceiver() { connectionReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED) { if (intent?.action == AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED) {
device = intent.getParcelableExtra("device", BluetoothDevice::class.java)!! device = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra("device", BluetoothDevice::class.java)!!
} else {
intent.getParcelableExtra("device") as BluetoothDevice?
}
val name = this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE) val name = this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE)
.getString("name", device?.name) .getString("name", device?.name)
if (this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE).getString("name", null) == null) { if (this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE).getString("name", null) == null) {
@@ -349,7 +361,11 @@ class AirPodsService: Service() {
addAction(AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED) addAction(AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED)
addAction(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED) addAction(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED)
} }
registerReceiver(connectionReceiver, deviceIntentFilter, RECEIVER_EXPORTED) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(connectionReceiver, deviceIntentFilter, RECEIVER_EXPORTED)
} else {
registerReceiver(connectionReceiver, deviceIntentFilter)
}
val bluetoothAdapter = getSystemService(BluetoothManager::class.java).adapter val bluetoothAdapter = getSystemService(BluetoothManager::class.java).adapter
bluetoothAdapter.bondedDevices.forEach { device -> bluetoothAdapter.bondedDevices.forEach { device ->
@@ -500,7 +516,6 @@ class AirPodsService: Service() {
) )
var justEnabledA2dp = false var justEnabledA2dp = false
earReceiver = object : BroadcastReceiver() { earReceiver = object : BroadcastReceiver() {
@SuppressLint("NewApi")
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val data = intent.getByteArrayExtra("data") val data = intent.getByteArrayExtra("data")
if (data != null && earDetectionEnabled) { if (data != null && earDetectionEnabled) {

View File

@@ -48,7 +48,6 @@ class Window (context: Context) {
private val mView: View private val mView: View
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@SuppressLint("NewApi")
private val mParams: WindowManager.LayoutParams = WindowManager.LayoutParams().apply { private val mParams: WindowManager.LayoutParams = WindowManager.LayoutParams().apply {
height = WindowManager.LayoutParams.WRAP_CONTENT height = WindowManager.LayoutParams.WRAP_CONTENT
width = WindowManager.LayoutParams.MATCH_PARENT width = WindowManager.LayoutParams.MATCH_PARENT