mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-04-21 21:52:33 +00:00
try adding widget; add previews to each composable
This commit is contained in:
@@ -61,7 +61,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".AirPodsService"
|
android:name=".services.AirPodsService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:foregroundServiceType="connectedDevice"
|
android:foregroundServiceType="connectedDevice"
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ package me.kavishdevar.aln
|
|||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.appwidget.AppWidgetProvider
|
import android.appwidget.AppWidgetProvider
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
|
import me.kavishdevar.aln.services.ServiceManager
|
||||||
|
import me.kavishdevar.aln.utils.BatteryComponent
|
||||||
|
import me.kavishdevar.aln.utils.BatteryStatus
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of App Widget functionality.
|
|
||||||
*/
|
|
||||||
class BatteryWidget : AppWidgetProvider() {
|
class BatteryWidget : AppWidgetProvider() {
|
||||||
override fun onUpdate(
|
override fun onUpdate(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -34,11 +35,36 @@ internal fun updateAppWidget(
|
|||||||
appWidgetManager: AppWidgetManager,
|
appWidgetManager: AppWidgetManager,
|
||||||
appWidgetId: Int
|
appWidgetId: Int
|
||||||
) {
|
) {
|
||||||
val widgetText = context.getString(R.string.appwidget_text)
|
val service = ServiceManager.getService()
|
||||||
// Construct the RemoteViews object
|
val batteryList = service?.batteryNotification?.getBattery()
|
||||||
val views = RemoteViews(context.packageName, R.layout.battery_widget)
|
|
||||||
views.setTextViewText(R.id.appwidget_text, widgetText)
|
val views = RemoteViews(context.packageName, R.layout.battery_widget)
|
||||||
|
Log.d("BatteryWidget", "Battery list: $batteryList")
|
||||||
|
|
||||||
|
views.setTextViewText(R.id.left_battery_widget,
|
||||||
|
batteryList?.find { it.component == BatteryComponent.LEFT }?.let {
|
||||||
|
if (it.status != BatteryStatus.DISCONNECTED) {
|
||||||
|
"${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
} ?: "")
|
||||||
|
views.setTextViewText(R.id.right_battery_widget,
|
||||||
|
batteryList?.find { it.component == BatteryComponent.RIGHT }?.let {
|
||||||
|
if (it.status != BatteryStatus.DISCONNECTED) {
|
||||||
|
"${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
} ?: "")
|
||||||
|
views.setTextViewText(R.id.case_battery_widget,
|
||||||
|
batteryList?.find { it.component == BatteryComponent.CASE }?.let {
|
||||||
|
if (it.status != BatteryStatus.DISCONNECTED) {
|
||||||
|
"${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
} ?: "")
|
||||||
|
|
||||||
// Instruct the widget manager to update the widget
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,9 @@ import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
|||||||
import me.kavishdevar.aln.screens.AirPodsSettingsScreen
|
import me.kavishdevar.aln.screens.AirPodsSettingsScreen
|
||||||
import me.kavishdevar.aln.screens.DebugScreen
|
import me.kavishdevar.aln.screens.DebugScreen
|
||||||
import me.kavishdevar.aln.screens.LongPress
|
import me.kavishdevar.aln.screens.LongPress
|
||||||
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
import me.kavishdevar.aln.ui.theme.ALNTheme
|
import me.kavishdevar.aln.ui.theme.ALNTheme
|
||||||
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
|
|
||||||
lateinit var serviceConnection: ServiceConnection
|
lateinit var serviceConnection: ServiceConnection
|
||||||
lateinit var connectionStatusReceiver: BroadcastReceiver
|
lateinit var connectionStatusReceiver: BroadcastReceiver
|
||||||
|
|||||||
@@ -1,463 +0,0 @@
|
|||||||
//@file:Suppress("unused")
|
|
||||||
//
|
|
||||||
//package me.kavishdevar.aln
|
|
||||||
//
|
|
||||||
//import android.annotation.SuppressLint
|
|
||||||
//import android.app.Notification
|
|
||||||
//import android.app.NotificationChannel
|
|
||||||
//import android.app.NotificationManager
|
|
||||||
//import android.app.Service
|
|
||||||
//import android.bluetooth.BluetoothDevice
|
|
||||||
//import android.bluetooth.BluetoothManager
|
|
||||||
//import android.bluetooth.BluetoothProfile
|
|
||||||
//import android.bluetooth.BluetoothSocket
|
|
||||||
//import android.content.BroadcastReceiver
|
|
||||||
//import android.content.Context
|
|
||||||
//import android.content.Intent
|
|
||||||
//import android.content.IntentFilter
|
|
||||||
//import android.media.AudioManager
|
|
||||||
//import android.os.Binder
|
|
||||||
//import android.os.Build
|
|
||||||
//import android.os.IBinder
|
|
||||||
//import android.os.ParcelUuid
|
|
||||||
//import android.util.Log
|
|
||||||
//import androidx.core.app.NotificationCompat
|
|
||||||
//import kotlinx.coroutines.CoroutineScope
|
|
||||||
//import kotlinx.coroutines.Dispatchers
|
|
||||||
//import kotlinx.coroutines.launch
|
|
||||||
//import org.lsposed.hiddenapibypass.HiddenApiBypass
|
|
||||||
//
|
|
||||||
//object ServiceManager {
|
|
||||||
// private var service: OldAirPodsService? = null
|
|
||||||
// @Synchronized
|
|
||||||
// fun getService(): OldAirPodsService? {
|
|
||||||
// return service
|
|
||||||
// }
|
|
||||||
// @Synchronized
|
|
||||||
// fun setService(service: OldAirPodsService?) {
|
|
||||||
// this.service = service
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//class OldAirPodsService : Service() {
|
|
||||||
// inner class LocalBinder : Binder() {
|
|
||||||
// fun getService(): OldAirPodsService = this@OldAirPodsService
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onBind(intent: Intent?): IBinder {
|
|
||||||
// return LocalBinder()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var isConnected: Boolean = false
|
|
||||||
// private var socket: BluetoothSocket? = null
|
|
||||||
//
|
|
||||||
// fun sendPacket(packet: String) {
|
|
||||||
// val fromHex = packet.split(" ").map { it.toInt(16).toByte() }
|
|
||||||
// socket?.outputStream?.write(fromHex.toByteArray())
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setANCMode(mode: Int) {
|
|
||||||
// when (mode) {
|
|
||||||
// 1 -> {
|
|
||||||
// socket?.outputStream?.write(Enums.NOISE_CANCELLATION_OFF.value)
|
|
||||||
// }
|
|
||||||
// 2 -> {
|
|
||||||
// socket?.outputStream?.write(Enums.NOISE_CANCELLATION_ON.value)
|
|
||||||
// }
|
|
||||||
// 3 -> {
|
|
||||||
// socket?.outputStream?.write(Enums.NOISE_CANCELLATION_TRANSPARENCY.value)
|
|
||||||
// }
|
|
||||||
// 4 -> {
|
|
||||||
// socket?.outputStream?.write(Enums.NOISE_CANCELLATION_ADAPTIVE.value)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setCAEnabled(enabled: Boolean) {
|
|
||||||
// socket?.outputStream?.write(if (enabled) Enums.SET_CONVERSATION_AWARENESS_ON.value else Enums.SET_CONVERSATION_AWARENESS_OFF.value)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setOffListeningMode(enabled: Boolean) {
|
|
||||||
// socket?.outputStream?.write(byteArrayOf(0x04, 0x00 ,0x04, 0x00, 0x09, 0x00, 0x34, if (enabled) 0x01 else 0x02, 0x00, 0x00, 0x00))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setAdaptiveStrength(strength: Int) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x2E, strength.toByte(), 0x00, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setPressSpeed(speed: Int) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x17, speed.toByte(), 0x00, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setPressAndHoldDuration(speed: Int) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x18, speed.toByte(), 0x00, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setNoiseCancellationWithOnePod(enabled: Boolean) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1B, if (enabled) 0x01 else 0x02, 0x00, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setVolumeControl(enabled: Boolean) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x25, if (enabled) 0x01 else 0x02, 0x00, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setVolumeSwipeSpeed(speed: Int) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x23, speed.toByte(), 0x00, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setToneVolume(volume: Int) {
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1F, volume.toByte(), 0x50, 0x00, 0x00)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val earDetectionNotification = AirPodsNotifications.EarDetection()
|
|
||||||
// val ancNotification = AirPodsNotifications.ANC()
|
|
||||||
// val batteryNotification = AirPodsNotifications.BatteryNotification()
|
|
||||||
// val conversationAwarenessNotification = AirPodsNotifications.ConversationalAwarenessNotification()
|
|
||||||
//
|
|
||||||
// var earDetectionEnabled = true
|
|
||||||
//
|
|
||||||
// fun setCaseChargingSounds(enabled: Boolean) {
|
|
||||||
// val bytes = byteArrayOf(0x12, 0x3a, 0x00, 0x01, 0x00, 0x08, if (enabled) 0x00 else 0x01)
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setEarDetection(enabled: Boolean) {
|
|
||||||
// earDetectionEnabled = enabled
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun getBattery(): List<Battery> {
|
|
||||||
// return batteryNotification.getBattery()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun getANC(): Int {
|
|
||||||
// return ancNotification.status
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun createNotification(): Notification {
|
|
||||||
// val channelId = "battery"
|
|
||||||
// val notificationBuilder = NotificationCompat.Builder(this, channelId)
|
|
||||||
// .setSmallIcon(R.drawable.pro_2_buds)
|
|
||||||
// .setContentTitle("AirPods Connected")
|
|
||||||
// .setOngoing(true)
|
|
||||||
// .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
||||||
//
|
|
||||||
// val channel =
|
|
||||||
// NotificationChannel(channelId, "Battery Notification", NotificationManager.IMPORTANCE_LOW)
|
|
||||||
//
|
|
||||||
// val notificationManager = getSystemService(NotificationManager::class.java)
|
|
||||||
// notificationManager.createNotificationChannel(channel)
|
|
||||||
// return notificationBuilder.build()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun disconnectAudio(context: Context, device: BluetoothDevice?) {
|
|
||||||
// val bluetoothAdapter = context.getSystemService(BluetoothManager::class.java).adapter
|
|
||||||
//
|
|
||||||
// bluetoothAdapter?.getProfileProxy(context, object : BluetoothProfile.ServiceListener {
|
|
||||||
// override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
|
|
||||||
// if (profile == BluetoothProfile.A2DP) {
|
|
||||||
// try {
|
|
||||||
// val method = proxy.javaClass.getMethod("disconnect", BluetoothDevice::class.java)
|
|
||||||
// method.invoke(proxy, device)
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// } finally {
|
|
||||||
// bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, proxy)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onServiceDisconnected(profile: Int) { }
|
|
||||||
// }, BluetoothProfile.A2DP)
|
|
||||||
//
|
|
||||||
// bluetoothAdapter?.getProfileProxy(context, object : BluetoothProfile.ServiceListener {
|
|
||||||
// override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
|
|
||||||
// if (profile == BluetoothProfile.HEADSET) {
|
|
||||||
// try {
|
|
||||||
// val method = proxy.javaClass.getMethod("disconnect", BluetoothDevice::class.java)
|
|
||||||
// method.invoke(proxy, device)
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// } finally {
|
|
||||||
// bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, proxy)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onServiceDisconnected(profile: Int) { }
|
|
||||||
// }, BluetoothProfile.HEADSET)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun connectAudio(context: Context, device: BluetoothDevice?) {
|
|
||||||
// val bluetoothAdapter = context.getSystemService(BluetoothManager::class.java).adapter
|
|
||||||
//
|
|
||||||
// bluetoothAdapter?.getProfileProxy(context, object : BluetoothProfile.ServiceListener {
|
|
||||||
// override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
|
|
||||||
// if (profile == BluetoothProfile.A2DP) {
|
|
||||||
// try {
|
|
||||||
// val method = proxy.javaClass.getMethod("connect", BluetoothDevice::class.java)
|
|
||||||
// method.invoke(proxy, device)
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// } finally {
|
|
||||||
// bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, proxy)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onServiceDisconnected(profile: Int) { }
|
|
||||||
// }, BluetoothProfile.A2DP)
|
|
||||||
//
|
|
||||||
// bluetoothAdapter?.getProfileProxy(context, object : BluetoothProfile.ServiceListener {
|
|
||||||
// override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
|
|
||||||
// if (profile == BluetoothProfile.HEADSET) {
|
|
||||||
// try {
|
|
||||||
// val method = proxy.javaClass.getMethod("connect", BluetoothDevice::class.java)
|
|
||||||
// method.invoke(proxy, device)
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// } finally {
|
|
||||||
// bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, proxy)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onServiceDisconnected(profile: Int) { }
|
|
||||||
// }, BluetoothProfile.HEADSET)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setName(name: String) {
|
|
||||||
// val nameBytes = name.toByteArray()
|
|
||||||
// val bytes = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x01,
|
|
||||||
// nameBytes.size.toByte(), 0x00) + nameBytes
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// socket?.outputStream?.flush()
|
|
||||||
// val hex = bytes.joinToString(" ") { "%02X".format(it) }
|
|
||||||
// Log.d("OldAirPodsService", "setName: $name, sent packet: $hex")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @SuppressLint("MissingPermission", "InlinedApi")
|
|
||||||
// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
||||||
//
|
|
||||||
// val notification = createNotification()
|
|
||||||
// startForeground(1, notification)
|
|
||||||
//
|
|
||||||
// ServiceManager.setService(this)
|
|
||||||
//
|
|
||||||
// if (isConnected) {
|
|
||||||
// return START_STICKY
|
|
||||||
// }
|
|
||||||
// isConnected = true
|
|
||||||
//
|
|
||||||
// @Suppress("DEPRECATION") val device = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) intent?.getParcelableExtra("device", BluetoothDevice::class.java) else intent?.getParcelableExtra("device")
|
|
||||||
//
|
|
||||||
// HiddenApiBypass.addHiddenApiExemptions("Landroid/bluetooth/BluetoothSocket;")
|
|
||||||
// val uuid: ParcelUuid = ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a")
|
|
||||||
//
|
|
||||||
// socket = HiddenApiBypass.newInstance(BluetoothSocket::class.java, 3, true, true, device, 0x1001, uuid) as BluetoothSocket?
|
|
||||||
// try {
|
|
||||||
// socket?.connect()
|
|
||||||
// socket?.let { it ->
|
|
||||||
// it.outputStream.write(Enums.HANDSHAKE.value)
|
|
||||||
// it.outputStream.write(Enums.SET_SPECIFIC_FEATURES.value)
|
|
||||||
// it.outputStream.write(Enums.REQUEST_NOTIFICATIONS.value)
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.AIRPODS_CONNECTED))
|
|
||||||
// it.outputStream.flush()
|
|
||||||
//
|
|
||||||
// CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
// while (socket?.isConnected == true) {
|
|
||||||
// socket?.let {
|
|
||||||
// val audioManager = this@OldAirPodsService.getSystemService(AUDIO_SERVICE) as AudioManager
|
|
||||||
// MediaController.initialize(audioManager)
|
|
||||||
// val buffer = ByteArray(1024)
|
|
||||||
// val bytesRead = it.inputStream.read(buffer)
|
|
||||||
// var data: ByteArray = byteArrayOf()
|
|
||||||
// if (bytesRead > 0) {
|
|
||||||
// data = buffer.copyOfRange(0, bytesRead)
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DATA).apply {
|
|
||||||
// putExtra("data", buffer.copyOfRange(0, bytesRead))
|
|
||||||
// })
|
|
||||||
// val bytes = buffer.copyOfRange(0, bytesRead)
|
|
||||||
// val formattedHex = bytes.joinToString(" ") { "%02X".format(it) }
|
|
||||||
// Log.d("AirPods Data", "Data received: $formattedHex")
|
|
||||||
// }
|
|
||||||
// else if (bytesRead == -1) {
|
|
||||||
// Log.d("AirPods Service", "Socket closed (bytesRead = -1)")
|
|
||||||
// this@OldAirPodsService.stopForeground(STOP_FOREGROUND_REMOVE)
|
|
||||||
// socket?.close()
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DISCONNECTED))
|
|
||||||
// return@launch
|
|
||||||
// }
|
|
||||||
// var inEar = false
|
|
||||||
// var inEarData = listOf<Boolean>()
|
|
||||||
// if (earDetectionNotification.isEarDetectionData(data)) {
|
|
||||||
// earDetectionNotification.setStatus(data)
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.EAR_DETECTION_DATA).apply {
|
|
||||||
// val list = earDetectionNotification.status
|
|
||||||
// val bytes = ByteArray(2)
|
|
||||||
// bytes[0] = list[0]
|
|
||||||
// bytes[1] = list[1]
|
|
||||||
// putExtra("data", bytes)
|
|
||||||
// })
|
|
||||||
// Log.d("AirPods Parser", "Ear Detection: ${earDetectionNotification.status[0]} ${earDetectionNotification.status[1]}")
|
|
||||||
// var justEnabledA2dp = false
|
|
||||||
// val earReceiver = object : BroadcastReceiver() {
|
|
||||||
// override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
// val data = intent.getByteArrayExtra("data")
|
|
||||||
// if (data != null && earDetectionEnabled) {
|
|
||||||
// inEar = if (data.find { it == 0x02.toByte() } != null || data.find { it == 0x03.toByte() } != null) {
|
|
||||||
// data[0] == 0x00.toByte() || data[1] == 0x00.toByte()
|
|
||||||
// } else {
|
|
||||||
// data[0] == 0x00.toByte() && data[1] == 0x00.toByte()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val newInEarData = listOf(data[0] == 0x00.toByte(), data[1] == 0x00.toByte())
|
|
||||||
// if (newInEarData.contains(true) && inEarData == listOf(false, false)) {
|
|
||||||
// connectAudio(this@OldAirPodsService, device)
|
|
||||||
// justEnabledA2dp = true
|
|
||||||
// val bluetoothAdapter = this@OldAirPodsService.getSystemService(BluetoothManager::class.java).adapter
|
|
||||||
// bluetoothAdapter.getProfileProxy(
|
|
||||||
// this@OldAirPodsService, object : BluetoothProfile.ServiceListener {
|
|
||||||
// override fun onServiceConnected(
|
|
||||||
// profile: Int,
|
|
||||||
// proxy: BluetoothProfile
|
|
||||||
// ) {
|
|
||||||
// if (profile == BluetoothProfile.A2DP) {
|
|
||||||
// val connectedDevices =
|
|
||||||
// proxy.connectedDevices
|
|
||||||
// if (connectedDevices.isNotEmpty()) {
|
|
||||||
// MediaController.sendPlay()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// bluetoothAdapter.closeProfileProxy(
|
|
||||||
// profile,
|
|
||||||
// proxy
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onServiceDisconnected(
|
|
||||||
// profile: Int
|
|
||||||
// ) {
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ,BluetoothProfile.A2DP
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// else if (newInEarData == listOf(false, false)){
|
|
||||||
// disconnectAudio(this@OldAirPodsService, device)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// inEarData = newInEarData
|
|
||||||
//
|
|
||||||
// if (inEar == true) {
|
|
||||||
// if (!justEnabledA2dp) {
|
|
||||||
// justEnabledA2dp = false
|
|
||||||
// MediaController.sendPlay()
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// MediaController.sendPause()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val earIntentFilter = IntentFilter(AirPodsNotifications.EAR_DETECTION_DATA)
|
|
||||||
// this@OldAirPodsService.registerReceiver(earReceiver, earIntentFilter,
|
|
||||||
// RECEIVER_EXPORTED
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// else if (ancNotification.isANCData(data)) {
|
|
||||||
// ancNotification.setStatus(data)
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.ANC_DATA).apply {
|
|
||||||
// putExtra("data", ancNotification.status)
|
|
||||||
// })
|
|
||||||
// Log.d("AirPods Parser", "ANC: ${ancNotification.status}")
|
|
||||||
// }
|
|
||||||
// else if (batteryNotification.isBatteryData(data)) {
|
|
||||||
// batteryNotification.setBattery(data)
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.BATTERY_DATA).apply {
|
|
||||||
// putParcelableArrayListExtra("data", ArrayList(batteryNotification.getBattery()))
|
|
||||||
// })
|
|
||||||
// for (battery in batteryNotification.getBattery()) {
|
|
||||||
// Log.d("AirPods Parser", "${battery.getComponentName()}: ${battery.getStatusName()} at ${battery.level}% ")
|
|
||||||
// }
|
|
||||||
//// if both are charging, disconnect audio profiles
|
|
||||||
// if (batteryNotification.getBattery()[0].status == 1 && batteryNotification.getBattery()[1].status == 1) {
|
|
||||||
// disconnectAudio(this@OldAirPodsService, device)
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// connectAudio(this@OldAirPodsService, device)
|
|
||||||
// }
|
|
||||||
//// updatePodsStatus(device!!, batteryNotification.getBattery())
|
|
||||||
// }
|
|
||||||
// else if (conversationAwarenessNotification.isConversationalAwarenessData(data)) {
|
|
||||||
// conversationAwarenessNotification.setData(data)
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.CA_DATA).apply {
|
|
||||||
// putExtra("data", conversationAwarenessNotification.status)
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// if (conversationAwarenessNotification.status == 1.toByte() || conversationAwarenessNotification.status == 2.toByte()) {
|
|
||||||
// MediaController.startSpeaking()
|
|
||||||
// } else if (conversationAwarenessNotification.status == 8.toByte() || conversationAwarenessNotification.status == 9.toByte()) {
|
|
||||||
// MediaController.stopSpeaking()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Log.d("AirPods Parser", "Conversation Awareness: ${conversationAwarenessNotification.status}")
|
|
||||||
// }
|
|
||||||
// else { }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Log.d("AirPods Service", "Socket closed")
|
|
||||||
// isConnected = false
|
|
||||||
// this@OldAirPodsService.stopForeground(STOP_FOREGROUND_REMOVE)
|
|
||||||
// socket?.close()
|
|
||||||
// sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DISCONNECTED))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (e: Exception) {
|
|
||||||
// Log.e("AirPodsSettingsScreen", "Error connecting to device: ${e.message}")
|
|
||||||
// }
|
|
||||||
// return START_STICKY
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onDestroy() {
|
|
||||||
// super.onDestroy()
|
|
||||||
// socket?.close()
|
|
||||||
// isConnected = false
|
|
||||||
// ServiceManager.setService(null)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setPVEnabled(enabled: Boolean) {
|
|
||||||
// var hex = "04 00 04 00 09 00 26 ${if (enabled) "01" else "02"} 00 00 00"
|
|
||||||
// var bytes = hex.split(" ").map { it.toInt(16).toByte() }.toByteArray()
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// hex = "04 00 04 00 17 00 00 00 10 00 12 00 08 E${if (enabled) "6" else "5"} 05 10 02 42 0B 08 50 10 02 1A 05 02 ${if (enabled) "32" else "00"} 00 00 00"
|
|
||||||
// bytes = hex.split(" ").map { it.toInt(16).toByte() }.toByteArray()
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setLoudSoundReduction(enabled: Boolean) {
|
|
||||||
// val hex = "52 1B 00 0${if (enabled) "1" else "0"}"
|
|
||||||
// val bytes = hex.split(" ").map { it.toInt(16).toByte() }.toByteArray()
|
|
||||||
// socket?.outputStream?.write(bytes)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@@ -18,7 +18,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AccessibilitySettings(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun AccessibilitySettings(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AudioSettings(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun AudioSettings(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.imageResource
|
import androidx.compose.ui.res.imageResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import me.kavishdevar.aln.AirPodsNotifications
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
import me.kavishdevar.aln.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
import me.kavishdevar.aln.Battery
|
import me.kavishdevar.aln.utils.Battery
|
||||||
import me.kavishdevar.aln.BatteryComponent
|
import me.kavishdevar.aln.utils.BatteryComponent
|
||||||
import me.kavishdevar.aln.BatteryStatus
|
import me.kavishdevar.aln.utils.BatteryStatus
|
||||||
import me.kavishdevar.aln.R
|
import me.kavishdevar.aln.R
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ConversationalAwarenessSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun ConversationalAwarenessSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun IndependentToggle(name: String, service: AirPodsService, functionName: String, sharedPreferences: SharedPreferences, default: Boolean = false) {
|
fun IndependentToggle(name: String, service: AirPodsService, functionName: String, sharedPreferences: SharedPreferences, default: Boolean = false) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LoudSoundReductionSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun LoudSoundReductionSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.kavishdevar.aln.composables
|
package me.kavishdevar.aln.composables
|
||||||
|
|
||||||
import me.kavishdevar.aln.R
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
@@ -20,6 +19,7 @@ import androidx.compose.ui.graphics.ImageBitmap
|
|||||||
import androidx.compose.ui.res.imageResource
|
import androidx.compose.ui.res.imageResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.kavishdevar.aln.R
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NoiseControlButton(
|
fun NoiseControlButton(
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ 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.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import me.kavishdevar.aln.AirPodsNotifications
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
import me.kavishdevar.aln.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
import me.kavishdevar.aln.NoiseControlMode
|
import me.kavishdevar.aln.utils.NoiseControlMode
|
||||||
import me.kavishdevar.aln.R
|
import me.kavishdevar.aln.R
|
||||||
|
|
||||||
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PersonalizedVolumeSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun PersonalizedVolumeSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SinglePodANCSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun SinglePodANCSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
import me.kavishdevar.aln.R
|
import me.kavishdevar.aln.R
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
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.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VolumeControlSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
fun VolumeControlSwitch(service: AirPodsService, sharedPreferences: SharedPreferences) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package me.kavishdevar.aln.receivers
|
|||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import me.kavishdevar.aln.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
|
||||||
class BootReceiver: BroadcastReceiver() {
|
class BootReceiver: BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
|||||||
@@ -14,8 +14,13 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
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.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Refresh
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
@@ -33,6 +38,8 @@ import androidx.compose.ui.geometry.Offset
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
@@ -46,8 +53,7 @@ import dev.chrisbanes.haze.haze
|
|||||||
import dev.chrisbanes.haze.hazeChild
|
import dev.chrisbanes.haze.hazeChild
|
||||||
import dev.chrisbanes.haze.materials.CupertinoMaterials
|
import dev.chrisbanes.haze.materials.CupertinoMaterials
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import me.kavishdevar.aln.AirPodsNotifications
|
import me.kavishdevar.aln.R
|
||||||
import me.kavishdevar.aln.AirPodsService
|
|
||||||
import me.kavishdevar.aln.composables.AccessibilitySettings
|
import me.kavishdevar.aln.composables.AccessibilitySettings
|
||||||
import me.kavishdevar.aln.composables.AudioSettings
|
import me.kavishdevar.aln.composables.AudioSettings
|
||||||
import me.kavishdevar.aln.composables.BatteryView
|
import me.kavishdevar.aln.composables.BatteryView
|
||||||
@@ -56,7 +62,10 @@ import me.kavishdevar.aln.composables.NavigationButton
|
|||||||
import me.kavishdevar.aln.composables.NoiseControlSettings
|
import me.kavishdevar.aln.composables.NoiseControlSettings
|
||||||
import me.kavishdevar.aln.composables.PressAndHoldSettings
|
import me.kavishdevar.aln.composables.PressAndHoldSettings
|
||||||
import me.kavishdevar.aln.composables.StyledTextField
|
import me.kavishdevar.aln.composables.StyledTextField
|
||||||
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
|
import me.kavishdevar.aln.services.ServiceManager
|
||||||
import me.kavishdevar.aln.ui.theme.ALNTheme
|
import me.kavishdevar.aln.ui.theme.ALNTheme
|
||||||
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class)
|
||||||
@SuppressLint("MissingPermission", "NewApi")
|
@SuppressLint("MissingPermission", "NewApi")
|
||||||
@@ -88,7 +97,13 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = deviceName.text
|
text = deviceName.text,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = if (darkMode) Color.White else Color.Black,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -116,23 +131,23 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
||||||
containerColor = Color.Transparent
|
containerColor = Color.Transparent
|
||||||
),
|
),
|
||||||
// actions = {
|
actions = {
|
||||||
// val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
// IconButton(
|
IconButton(
|
||||||
// onClick = {
|
onClick = {
|
||||||
// ServiceManager.restartService(context)
|
ServiceManager.restartService(context)
|
||||||
// },
|
},
|
||||||
// colors = IconButtonDefaults.iconButtonColors(
|
colors = IconButtonDefaults.iconButtonColors(
|
||||||
// containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
// contentColor = if (isSystemInDarkTheme()) Color.White else Color.Black
|
contentColor = if (isSystemInDarkTheme()) Color.White else Color.Black
|
||||||
// )
|
)
|
||||||
// ) {
|
) {
|
||||||
// Icon(
|
Icon(
|
||||||
// imageVector = Icons.Default.Refresh,
|
imageVector = Icons.Default.Refresh,
|
||||||
// contentDescription = "Settings",
|
contentDescription = "Settings",
|
||||||
// )
|
)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
@@ -228,7 +243,8 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 24.sp,
|
fontSize = 24.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
color = if (isSystemInDarkTheme()) Color.White else Color.Black
|
color = if (isSystemInDarkTheme()) Color.White else Color.Black,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
@@ -239,7 +255,8 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Light,
|
||||||
color = if (isSystemInDarkTheme()) Color.White else Color.Black
|
color = if (isSystemInDarkTheme()) Color.White else Color.Black,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
@@ -253,9 +270,13 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun AirPodsSettingsScreenPreview() {
|
fun AirPodsSettingsScreenPreview() {
|
||||||
ALNTheme (
|
Column (
|
||||||
darkTheme = true
|
modifier = Modifier.height(2000.dp)
|
||||||
) {
|
) {
|
||||||
AirPodsSettingsScreen(dev = null, service = AirPodsService(), navController = rememberNavController(), isConnected = true)
|
ALNTheme (
|
||||||
|
darkTheme = true
|
||||||
|
) {
|
||||||
|
AirPodsSettingsScreen(dev = null, service = AirPodsService(), navController = rememberNavController(), isConnected = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,8 +61,8 @@ import dev.chrisbanes.haze.haze
|
|||||||
import dev.chrisbanes.haze.hazeChild
|
import dev.chrisbanes.haze.hazeChild
|
||||||
import dev.chrisbanes.haze.materials.CupertinoMaterials
|
import dev.chrisbanes.haze.materials.CupertinoMaterials
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import me.kavishdevar.aln.AirPodsNotifications
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
import me.kavishdevar.aln.AirPodsService
|
import me.kavishdevar.aln.services.AirPodsService
|
||||||
import me.kavishdevar.aln.R
|
import me.kavishdevar.aln.R
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import me.kavishdevar.aln.R
|
import me.kavishdevar.aln.R
|
||||||
import me.kavishdevar.aln.ServiceManager
|
import me.kavishdevar.aln.services.ServiceManager
|
||||||
|
|
||||||
@Composable()
|
@Composable()
|
||||||
fun RightDivider() {
|
fun RightDivider() {
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ import android.content.IntentFilter
|
|||||||
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
|
||||||
import me.kavishdevar.aln.AirPodsNotifications
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
import me.kavishdevar.aln.NoiseControlMode
|
import me.kavishdevar.aln.utils.NoiseControlMode
|
||||||
import me.kavishdevar.aln.ServiceManager
|
|
||||||
|
|
||||||
class AirPodsQSService: TileService() {
|
class AirPodsQSService: TileService() {
|
||||||
private val ancModes = listOf(NoiseControlMode.NOISE_CANCELLATION.name, NoiseControlMode.TRANSPARENCY.name, NoiseControlMode.ADAPTIVE.name)
|
private val ancModes = listOf(NoiseControlMode.NOISE_CANCELLATION.name, NoiseControlMode.TRANSPARENCY.name, NoiseControlMode.ADAPTIVE.name)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.kavishdevar.aln
|
package me.kavishdevar.aln.services
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
@@ -25,6 +25,14 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.kavishdevar.aln.utils.AirPodsNotifications
|
||||||
|
import me.kavishdevar.aln.utils.Battery
|
||||||
|
import me.kavishdevar.aln.utils.BatteryComponent
|
||||||
|
import me.kavishdevar.aln.utils.BatteryStatus
|
||||||
|
import me.kavishdevar.aln.utils.Enums
|
||||||
|
import me.kavishdevar.aln.utils.LongPressPackets
|
||||||
|
import me.kavishdevar.aln.R
|
||||||
|
import me.kavishdevar.aln.utils.Window
|
||||||
import me.kavishdevar.aln.utils.MediaController
|
import me.kavishdevar.aln.utils.MediaController
|
||||||
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
||||||
|
|
||||||
@@ -38,11 +46,11 @@ object ServiceManager {
|
|||||||
fun setService(service: AirPodsService?) {
|
fun setService(service: AirPodsService?) {
|
||||||
this.service = service
|
this.service = service
|
||||||
}
|
}
|
||||||
// @Synchronized
|
@Synchronized
|
||||||
// fun restartService(context: Context) {
|
fun restartService(context: Context) {
|
||||||
// service?.stopSelf()
|
service?.stopSelf()
|
||||||
// context.startService(Intent(context, AirPodsService::class.java))
|
context.startService(Intent(context, AirPodsService::class.java))
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@@ -84,7 +92,7 @@ class AirPodsService: Service() {
|
|||||||
}
|
}
|
||||||
val uuid = ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a")
|
val uuid = ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a")
|
||||||
if (bluetoothDevice.uuids.contains(uuid)) {
|
if (bluetoothDevice.uuids.contains(uuid)) {
|
||||||
val intent = Intent(AirPodsNotifications.AIRPODS_CONNECTION_DETECTED)
|
val intent = Intent(AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED)
|
||||||
intent.putExtra("name", name)
|
intent.putExtra("name", name)
|
||||||
intent.putExtra("device", bluetoothDevice)
|
intent.putExtra("device", bluetoothDevice)
|
||||||
context?.sendBroadcast(intent)
|
context?.sendBroadcast(intent)
|
||||||
@@ -94,7 +102,7 @@ class AirPodsService: Service() {
|
|||||||
|| BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED == action
|
|| BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED == action
|
||||||
) {
|
) {
|
||||||
context?.sendBroadcast(
|
context?.sendBroadcast(
|
||||||
Intent(AirPodsNotifications.AIRPODS_DISCONNECTED)
|
Intent(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +203,6 @@ class AirPodsService: Service() {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the NotificationManager with the same ID
|
|
||||||
notificationManager.notify(1, updatedNotification)
|
notificationManager.notify(1, updatedNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,11 +226,12 @@ class AirPodsService: Service() {
|
|||||||
addAction("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED")
|
addAction("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED")
|
||||||
addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED")
|
addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED")
|
||||||
}
|
}
|
||||||
|
|
||||||
registerReceiver(bluetoothReceiver, serviceIntentFilter, RECEIVER_EXPORTED)
|
registerReceiver(bluetoothReceiver, serviceIntentFilter, RECEIVER_EXPORTED)
|
||||||
|
|
||||||
connectionReceiver = object: BroadcastReceiver() {
|
connectionReceiver = object: BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (intent?.action == AirPodsNotifications.AIRPODS_CONNECTION_DETECTED) {
|
if (intent?.action == AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED) {
|
||||||
val name = this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE)
|
val name = this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE)
|
||||||
.getString("name", device?.name)
|
.getString("name", device?.name)
|
||||||
Log.d("AirPodsService", "$name connected")
|
Log.d("AirPodsService", "$name connected")
|
||||||
@@ -232,7 +240,7 @@ class AirPodsService: Service() {
|
|||||||
connectToSocket(device!!)
|
connectToSocket(device!!)
|
||||||
updateNotificationContent(true, name.toString(), batteryNotification.getBattery())
|
updateNotificationContent(true, name.toString(), batteryNotification.getBattery())
|
||||||
}
|
}
|
||||||
else if (intent?.action == AirPodsNotifications.AIRPODS_DISCONNECTED) {
|
else if (intent?.action == AirPodsNotifications.Companion.AIRPODS_DISCONNECTED) {
|
||||||
device = null
|
device = null
|
||||||
isConnected = false
|
isConnected = false
|
||||||
popupShown = false
|
popupShown = false
|
||||||
@@ -242,8 +250,8 @@ class AirPodsService: Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val deviceIntentFilter = IntentFilter().apply {
|
val deviceIntentFilter = IntentFilter().apply {
|
||||||
addAction(AirPodsNotifications.AIRPODS_CONNECTION_DETECTED)
|
addAction(AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED)
|
||||||
addAction(AirPodsNotifications.AIRPODS_DISCONNECTED)
|
addAction(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED)
|
||||||
}
|
}
|
||||||
registerReceiver(connectionReceiver, deviceIntentFilter, RECEIVER_EXPORTED)
|
registerReceiver(connectionReceiver, deviceIntentFilter, RECEIVER_EXPORTED)
|
||||||
|
|
||||||
@@ -257,7 +265,7 @@ class AirPodsService: Service() {
|
|||||||
if (connectedDevices.isNotEmpty()) {
|
if (connectedDevices.isNotEmpty()) {
|
||||||
connectToSocket(device)
|
connectToSocket(device)
|
||||||
this@AirPodsService.sendBroadcast(
|
this@AirPodsService.sendBroadcast(
|
||||||
Intent(AirPodsNotifications.AIRPODS_CONNECTED)
|
Intent(AirPodsNotifications.Companion.AIRPODS_CONNECTED)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,7 +356,7 @@ class AirPodsService: Service() {
|
|||||||
it.outputStream.flush()
|
it.outputStream.flush()
|
||||||
delay(200)
|
delay(200)
|
||||||
sendBroadcast(
|
sendBroadcast(
|
||||||
Intent(AirPodsNotifications.AIRPODS_CONNECTED)
|
Intent(AirPodsNotifications.Companion.AIRPODS_CONNECTED)
|
||||||
.putExtra("device", device)
|
.putExtra("device", device)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -362,7 +370,7 @@ class AirPodsService: Service() {
|
|||||||
var data: ByteArray = byteArrayOf()
|
var data: ByteArray = byteArrayOf()
|
||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
data = buffer.copyOfRange(0, bytesRead)
|
data = buffer.copyOfRange(0, bytesRead)
|
||||||
sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DATA).apply {
|
sendBroadcast(Intent(AirPodsNotifications.Companion.AIRPODS_DATA).apply {
|
||||||
putExtra("data", buffer.copyOfRange(0, bytesRead))
|
putExtra("data", buffer.copyOfRange(0, bytesRead))
|
||||||
})
|
})
|
||||||
val bytes = buffer.copyOfRange(0, bytesRead)
|
val bytes = buffer.copyOfRange(0, bytesRead)
|
||||||
@@ -371,14 +379,14 @@ class AirPodsService: Service() {
|
|||||||
} else if (bytesRead == -1) {
|
} else if (bytesRead == -1) {
|
||||||
Log.d("AirPods Service", "Socket closed (bytesRead = -1)")
|
Log.d("AirPods Service", "Socket closed (bytesRead = -1)")
|
||||||
// socket.close()
|
// socket.close()
|
||||||
sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DISCONNECTED))
|
sendBroadcast(Intent(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED))
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
var inEar = false
|
var inEar = false
|
||||||
var inEarData = listOf<Boolean>()
|
var inEarData = listOf<Boolean>()
|
||||||
if (earDetectionNotification.isEarDetectionData(data)) {
|
if (earDetectionNotification.isEarDetectionData(data)) {
|
||||||
earDetectionNotification.setStatus(data)
|
earDetectionNotification.setStatus(data)
|
||||||
sendBroadcast(Intent(AirPodsNotifications.EAR_DETECTION_DATA).apply {
|
sendBroadcast(Intent(AirPodsNotifications.Companion.EAR_DETECTION_DATA).apply {
|
||||||
val list = earDetectionNotification.status
|
val list = earDetectionNotification.status
|
||||||
val bytes = ByteArray(2)
|
val bytes = ByteArray(2)
|
||||||
bytes[0] = list[0]
|
bytes[0] = list[0]
|
||||||
@@ -463,7 +471,7 @@ class AirPodsService: Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val earIntentFilter =
|
val earIntentFilter =
|
||||||
IntentFilter(AirPodsNotifications.EAR_DETECTION_DATA)
|
IntentFilter(AirPodsNotifications.Companion.EAR_DETECTION_DATA)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
this@AirPodsService.registerReceiver(
|
this@AirPodsService.registerReceiver(
|
||||||
earReceiver, earIntentFilter,
|
earReceiver, earIntentFilter,
|
||||||
@@ -477,13 +485,13 @@ class AirPodsService: Service() {
|
|||||||
}
|
}
|
||||||
} else if (ancNotification.isANCData(data)) {
|
} else if (ancNotification.isANCData(data)) {
|
||||||
ancNotification.setStatus(data)
|
ancNotification.setStatus(data)
|
||||||
sendBroadcast(Intent(AirPodsNotifications.ANC_DATA).apply {
|
sendBroadcast(Intent(AirPodsNotifications.Companion.ANC_DATA).apply {
|
||||||
putExtra("data", ancNotification.status)
|
putExtra("data", ancNotification.status)
|
||||||
})
|
})
|
||||||
Log.d("AirPods Parser", "ANC: ${ancNotification.status}")
|
Log.d("AirPods Parser", "ANC: ${ancNotification.status}")
|
||||||
} else if (batteryNotification.isBatteryData(data)) {
|
} else if (batteryNotification.isBatteryData(data)) {
|
||||||
batteryNotification.setBattery(data)
|
batteryNotification.setBattery(data)
|
||||||
sendBroadcast(Intent(AirPodsNotifications.BATTERY_DATA).apply {
|
sendBroadcast(Intent(AirPodsNotifications.Companion.BATTERY_DATA).apply {
|
||||||
putParcelableArrayListExtra(
|
putParcelableArrayListExtra(
|
||||||
"data",
|
"data",
|
||||||
ArrayList(batteryNotification.getBattery())
|
ArrayList(batteryNotification.getBattery())
|
||||||
@@ -513,7 +521,7 @@ class AirPodsService: Service() {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
conversationAwarenessNotification.setData(data)
|
conversationAwarenessNotification.setData(data)
|
||||||
sendBroadcast(Intent(AirPodsNotifications.CA_DATA).apply {
|
sendBroadcast(Intent(AirPodsNotifications.Companion.CA_DATA).apply {
|
||||||
putExtra("data", conversationAwarenessNotification.status)
|
putExtra("data", conversationAwarenessNotification.status)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -535,7 +543,7 @@ class AirPodsService: Service() {
|
|||||||
Log.d("AirPods Service", "Socket closed")
|
Log.d("AirPods Service", "Socket closed")
|
||||||
isConnected = false
|
isConnected = false
|
||||||
socket.close()
|
socket.close()
|
||||||
sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DISCONNECTED))
|
sendBroadcast(Intent(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
@file:Suppress("unused")
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package me.kavishdevar.aln
|
package me.kavishdevar.aln.utils
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.kavishdevar.aln
|
package me.kavishdevar.aln.utils
|
||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.animation.AnimatorListenerAdapter
|
import android.animation.AnimatorListenerAdapter
|
||||||
@@ -22,7 +22,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.lang.Exception
|
import me.kavishdevar.aln.R
|
||||||
|
|
||||||
@SuppressLint("InflateParams", "ClickableViewAccessibility")
|
@SuppressLint("InflateParams", "ClickableViewAccessibility")
|
||||||
class Window (context: Context) {
|
class Window (context: Context) {
|
||||||
@@ -4,7 +4,6 @@ appWidgetInnerRadius attribute value
|
|||||||
-->
|
-->
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<corners android:radius="?attr/appWidgetInnerRadius" />
|
<corners android:radius="?attr/appWidgetInnerRadius" />
|
||||||
<solid android:color="?android:attr/colorAccent" />
|
<solid android:color="?android:attr/colorAccent" />
|
||||||
</shape>
|
</shape>
|
||||||
72
android/app/src/main/res/layout-v31/battery_widget.xml
Normal file
72
android/app/src/main/res/layout-v31/battery_widget.xml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
style="@style/Widget.ALN.AppWidget.Container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:theme="@style/Theme.ALN.AppWidgetContainer">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:contentDescription="something"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="0dp"
|
||||||
|
android:src="@drawable/airpods_pro_left_notification"
|
||||||
|
android:tint="@android:color/system_accent2_400"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/left_battery_widget"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@android:color/system_accent2_400"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="Left"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:src="@drawable/airpods_pro_right_notification"
|
||||||
|
android:tint="@android:color/system_accent2_400"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:contentDescription="something"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/right_battery_widget"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@android:color/system_accent2_400"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="Right"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:src="@drawable/airpods_pro_case_notification"
|
||||||
|
android:tint="@android:color/system_accent2_400"
|
||||||
|
android:contentDescription="something"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/case_battery_widget"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@android:color/system_accent2_400"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="Case"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
@@ -1,19 +1,74 @@
|
|||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
style="@style/Widget.ALN.AppWidget.Container"
|
style="@style/Widget.ALN.AppWidget.Container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:theme="@style/Theme.ALN.AppWidgetContainer">
|
android:theme="@style/Theme.ALN.AppWidgetContainer">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:gravity="center">
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:contentDescription="something"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="0dp"
|
||||||
|
android:src="@drawable/airpods_pro_left_notification"
|
||||||
|
android:tint="@color/popup_text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/appwidget_text"
|
android:id="@+id/left_battery_widget"
|
||||||
style="@style/Widget.ALN.AppWidget.InnerView"
|
android:layout_width="0dp"
|
||||||
android:layout_width="wrap_content"
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerHorizontal="true"
|
android:textSize="24sp"
|
||||||
android:layout_centerVertical="true"
|
android:textColor="@color/popup_text"
|
||||||
android:layout_margin="8dp"
|
android:layout_marginHorizontal="8dp"
|
||||||
android:contentDescription="@string/appwidget_text"
|
android:gravity="center_vertical"
|
||||||
android:text="@string/appwidget_text"
|
android:text="Left"
|
||||||
android:textSize="24sp"
|
tools:ignore="HardcodedText" />
|
||||||
android:textStyle="bold|italic" />
|
<ImageView
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:src="@drawable/airpods_pro_right_notification"
|
||||||
|
android:tint="@color/popup_text"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:contentDescription="something"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/right_battery_widget"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@color/popup_text"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="Right"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:src="@drawable/airpods_pro_case_notification"
|
||||||
|
android:tint="@color/popup_text"
|
||||||
|
android:contentDescription="something"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/case_battery_widget"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@color/popup_text"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="Case"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
@@ -2,4 +2,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<color name="popup_background">#1C1B1E</color>
|
<color name="popup_background">#1C1B1E</color>
|
||||||
<color name="popup_text">@color/white</color>
|
<color name="popup_text">@color/white</color>
|
||||||
|
<color name="widget_background">#1C1B1E</color>
|
||||||
|
<color name="widget_text">@color/white</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
<color name="popup_background">#FFFFFF</color>
|
<color name="popup_background">#FFFFFF</color>
|
||||||
<color name="popup_text">@color/black</color>
|
<color name="popup_text">@color/black</color>
|
||||||
<color name="light_blue_50">#FFE1F5FE</color>
|
<color name="widget_background">#87FFFFFF</color>
|
||||||
<color name="light_blue_200">#FF81D4FA</color>
|
<color name="widget_text">@color/black</color>
|
||||||
<color name="light_blue_600">#FF039BE5</color>
|
|
||||||
<color name="light_blue_900">#FF01579B</color>
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">ALN</string>
|
<string name="app_name">ALN</string>
|
||||||
<string name="title_activity_custom_device">GATT Testing</string>
|
<string name="title_activity_custom_device">GATT Testing</string>
|
||||||
<string name="appwidget_text">EXAMPLE</string>
|
<string name="app_widget_description">See your AirPods battery status right from your home screen!</string>
|
||||||
<string name="add_widget">Add widget</string>
|
|
||||||
<string name="app_widget_description">This is an app widget description</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
<style name="Theme.ALN.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
|
<style name="Theme.ALN.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
|
||||||
<!-- Radius of the outer bound of widgets to make the rounded corners -->
|
<!-- Radius of the outer bound of widgets to make the rounded corners -->
|
||||||
<item name="appWidgetRadius">16dp</item>
|
<item name="appWidgetRadius">24dp</item>
|
||||||
<!--
|
<!--
|
||||||
Radius of the inner view's bound of widgets to make the rounded corners.
|
Radius of the inner view's bound of widgets to make the rounded corners.
|
||||||
It needs to be 8dp or less than the value of appWidgetRadius
|
It needs to be 8dp or less than the value of appWidgetRadius
|
||||||
-->
|
-->
|
||||||
<item name="appWidgetInnerRadius">8dp</item>
|
<item name="appWidgetInnerRadius">24dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.ALN.AppWidgetContainer" parent="Theme.ALN.AppWidgetContainerParent">
|
<style name="Theme.ALN.AppWidgetContainer" parent="Theme.ALN.AppWidgetContainerParent">
|
||||||
|
|||||||
14
android/app/src/main/res/xml-v31/battery_widget_info.xml
Normal file
14
android/app/src/main/res/xml-v31/battery_widget_info.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:description="@string/app_widget_description"
|
||||||
|
android:initialKeyguardLayout="@layout/battery_widget"
|
||||||
|
android:initialLayout="@layout/battery_widget"
|
||||||
|
android:minWidth="40dp"
|
||||||
|
android:minHeight="40dp"
|
||||||
|
android:previewImage="@drawable/example_appwidget_preview"
|
||||||
|
android:previewLayout="@layout/battery_widget"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:targetCellWidth="1"
|
||||||
|
android:targetCellHeight="1"
|
||||||
|
android:updatePeriodMillis="86400000"
|
||||||
|
android:widgetCategory="home_screen|keyguard" />
|
||||||
Reference in New Issue
Block a user