From f67e5defcfc095af248d0d238c4eca8d4aa54a17 Mon Sep 17 00:00:00 2001 From: Kavish Devar Date: Sun, 26 Jan 2025 19:14:53 +0530 Subject: [PATCH] add iOS style battery widget --- android/app/src/main/AndroidManifest.xml | 7 +- .../aln/composables/NoiseControlSettings.kt | 4 +- .../aln/screens/AppSettingsScreen.kt | 4 + .../aln/services/AirPodsService.kt | 252 ++++++++++++++++-- .../aln/{ => widgets}/BatteryWidget.kt | 44 +-- .../src/main/res/drawable/blur_background.xml | 7 - .../main/res/drawable/button_background.xml | 14 + .../res/drawable/circular_progress_bar.xml | 18 +- .../app/src/main/res/drawable/ic_power.xml | 15 ++ .../drawable/{shape.xml => popup_shape.xml} | 4 +- .../res/drawable/progress_bar_background.xml | 11 + .../app/src/main/res/drawable/smartphone.xml | 19 ++ .../main/res/drawable/widget_background.xml | 9 + .../src/main/res/layout/battery_widget.xml | 196 ++++++++++++-- .../app/src/main/res/layout/popup_window.xml | 2 +- android/app/src/main/res/values/themes.xml | 12 +- .../src/main/res/xml/battery_widget_info.xml | 8 +- 17 files changed, 505 insertions(+), 121 deletions(-) rename android/app/src/main/java/me/kavishdevar/aln/{ => widgets}/BatteryWidget.kt (56%) delete mode 100644 android/app/src/main/res/drawable/blur_background.xml create mode 100644 android/app/src/main/res/drawable/button_background.xml create mode 100644 android/app/src/main/res/drawable/ic_power.xml rename android/app/src/main/res/drawable/{shape.xml => popup_shape.xml} (77%) create mode 100644 android/app/src/main/res/drawable/progress_bar_background.xml create mode 100644 android/app/src/main/res/drawable/smartphone.xml create mode 100644 android/app/src/main/res/drawable/widget_background.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 01003e0..fe3884c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -11,8 +11,9 @@ - + diff --git a/android/app/src/main/java/me/kavishdevar/aln/composables/NoiseControlSettings.kt b/android/app/src/main/java/me/kavishdevar/aln/composables/NoiseControlSettings.kt index f962537..d7d6289 100644 --- a/android/app/src/main/java/me/kavishdevar/aln/composables/NoiseControlSettings.kt +++ b/android/app/src/main/java/me/kavishdevar/aln/composables/NoiseControlSettings.kt @@ -321,8 +321,8 @@ fun NoiseControlSettings(service: AirPodsService) { Box( modifier = Modifier .fillMaxSize() - .padding(4.dp) - .background(selectedBackground, RoundedCornerShape(11.dp)) + .padding(3.dp) + .background(selectedBackground, RoundedCornerShape(12.dp)) ) } diff --git a/android/app/src/main/java/me/kavishdevar/aln/screens/AppSettingsScreen.kt b/android/app/src/main/java/me/kavishdevar/aln/screens/AppSettingsScreen.kt index 499813c..918ccab 100644 --- a/android/app/src/main/java/me/kavishdevar/aln/screens/AppSettingsScreen.kt +++ b/android/app/src/main/java/me/kavishdevar/aln/screens/AppSettingsScreen.kt @@ -69,7 +69,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import me.kavishdevar.aln.R +import me.kavishdevar.aln.composables.IndependentToggle import me.kavishdevar.aln.composables.StyledSwitch +import me.kavishdevar.aln.services.ServiceManager import kotlin.math.roundToInt @OptIn(ExperimentalMaterial3Api::class) @@ -130,6 +132,8 @@ fun AppSettingsScreen(navController: NavController) { val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF) val textColor = if (isDarkTheme) Color.White else Color.Black + IndependentToggle("Show phone battery in widget", ServiceManager.getService()!!, "setPhoneBatteryInWidget", sharedPreferences) + Column ( modifier = Modifier .fillMaxWidth() diff --git a/android/app/src/main/java/me/kavishdevar/aln/services/AirPodsService.kt b/android/app/src/main/java/me/kavishdevar/aln/services/AirPodsService.kt index eb6e816..cf3f53d 100644 --- a/android/app/src/main/java/me/kavishdevar/aln/services/AirPodsService.kt +++ b/android/app/src/main/java/me/kavishdevar/aln/services/AirPodsService.kt @@ -28,6 +28,7 @@ import android.app.Service import android.appwidget.AppWidgetManager import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice +import android.bluetooth.BluetoothHeadset import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile import android.bluetooth.BluetoothSocket @@ -42,6 +43,7 @@ import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences import android.media.AudioManager +import android.os.BatteryManager import android.os.Binder import android.os.Build import android.os.Handler @@ -49,10 +51,12 @@ import android.os.IBinder import android.os.Looper import android.os.ParcelUuid import android.util.Log +import android.view.View import android.widget.RemoteViews import androidx.annotation.RequiresPermission import androidx.compose.material3.ExperimentalMaterial3Api import androidx.core.app.NotificationCompat +import androidx.core.content.edit import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.awaitClose @@ -62,7 +66,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.launch -import me.kavishdevar.aln.BatteryWidget import me.kavishdevar.aln.MainActivity import me.kavishdevar.aln.R import me.kavishdevar.aln.utils.AirPodsNotifications @@ -75,6 +78,7 @@ import me.kavishdevar.aln.utils.Enums import me.kavishdevar.aln.utils.LongPressPackets import me.kavishdevar.aln.utils.MediaController import me.kavishdevar.aln.utils.Window +import me.kavishdevar.aln.widgets.BatteryWidget import org.lsposed.hiddenapibypass.HiddenApiBypass object ServiceManager { @@ -103,7 +107,7 @@ object ServiceManager { } } -//@Suppress("unused") +// @Suppress("unused") class AirPodsService: Service() { private var macAddress = "" inner class LocalBinder : Binder() { @@ -115,7 +119,6 @@ class AirPodsService: Service() { private val _packetLogsFlow = MutableStateFlow>(emptySet()) val packetLogsFlow: StateFlow> get() = _packetLogsFlow - override fun onCreate() { super.onCreate() sharedPreferences = getSharedPreferences("packet_logs", MODE_PRIVATE) @@ -127,7 +130,7 @@ class AirPodsService: Service() { val logs = sharedPreferences.getStringSet(packetLogKey, mutableSetOf())?.toMutableSet() ?: mutableSetOf() logs.add(logEntry) _packetLogsFlow.value = logs - sharedPreferences.edit().putStringSet(packetLogKey, logs).apply() + sharedPreferences.edit { putStringSet(packetLogKey, logs) } } fun getPacketLogs(): Set { @@ -135,7 +138,8 @@ class AirPodsService: Service() { } private fun clearPacketLogs() { - sharedPreferences.edit().remove(packetLogKey).apply() + sharedPreferences.edit { remove(packetLogKey).apply() } + } fun clearLogs() { @@ -198,7 +202,148 @@ class AirPodsService: Service() { var device: BluetoothDevice? = null private lateinit var earReceiver: BroadcastReceiver + var widgetMobileBatteryEnabled = false + val METADATA_UNTETHERED_LEFT_CHARGING = 13 + val METADATA_UNTETHERED_LEFT_BATTERY = 10 + val METADATA_UNTETHERED_RIGHT_CHARGING = 14 + val METADATA_UNTETHERED_RIGHT_BATTERY = 11 + val METADATA_UNTETHERED_CASE_CHARGING = 15 + val METADATA_UNTETHERED_CASE_BATTERY = 12 + + @SuppressLint("MissingPermission") + fun setBatteryLevels( + leftStatus: Boolean, leftLevel: Int, + rightStatus: Boolean, rightLevel: Int, + caseStatus: Boolean, caseLevel: Int, + device: BluetoothDevice + ) { + HiddenApiBypass.addHiddenApiExemptions("Landroid/bluetooth/BluetoothDevice;") + + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "setMetadata", + METADATA_UNTETHERED_LEFT_CHARGING, + leftStatus.toString().toByteArray() + ) + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "setMetadata", + METADATA_UNTETHERED_LEFT_BATTERY, + leftLevel.toString().toByteArray() + ) + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "setMetadata", + METADATA_UNTETHERED_RIGHT_CHARGING, + rightStatus.toString().toByteArray() + ) + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "setMetadata", + METADATA_UNTETHERED_RIGHT_BATTERY, + rightLevel.toString().toByteArray() + ) + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "setMetadata", + METADATA_UNTETHERED_CASE_CHARGING, + caseStatus.toString().toByteArray() + ) + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "setMetadata", + METADATA_UNTETHERED_CASE_BATTERY, + caseLevel.toString().toByteArray() + ) + HiddenApiBypass.invoke( + BluetoothDevice::class.java, + device, + "sendVendorSpecificHeadsetEvent", + "+IPHONEACCEV", + BluetoothHeadset.AT_CMD_TYPE_SET, + 1, + leftLevel, + 2, + rightLevel, + 3, + caseLevel + ) + + // Prepare the intent to broadcast vendor-specific headset event + val intent = Intent(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT).apply { + putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD, "+IPHONEACCEV") + putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE, BluetoothHeadset.AT_CMD_TYPE_SET) + putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS, arrayOf( + 1, leftLevel, + 2, rightLevel, + 3, caseLevel + )) + putExtra(BluetoothDevice.EXTRA_DEVICE, device) + putExtra(BluetoothDevice.EXTRA_NAME, device.name) + addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + 76) + } + + // Send the broadcast to update the battery levels + sendBroadcast(intent) + + // Broadcast battery level changes + val batteryIntent = Intent("android.bluet9ooth.device.action.BATTERY_LEVEL_CHANGED").apply { + putExtra(BluetoothDevice.EXTRA_DEVICE, device) + putExtra("android.bluetooth.device.extra.BATTERY_LEVEL", leftLevel) // Update with appropriate levels + } + sendBroadcast(batteryIntent) + } + + object PhoneBatteryReceiver: BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent) { + if (intent.action == Intent.ACTION_BATTERY_CHANGED) { + ServiceManager.getService()?.updateBatteryWidget() + } + else if (intent.action == AirPodsNotifications.DISCONNECT_RECEIVERS) { + try { + context?.unregisterReceiver(this) + } catch (e: Exception) { + e.printStackTrace() + } + } + } + } + val phoneBatteryIntentFilter = IntentFilter().apply { + addAction(Intent.ACTION_BATTERY_CHANGED) + addAction(AirPodsNotifications.DISCONNECT_RECEIVERS) + } + fun setPhoneBatteryInWidget(enabled: Boolean) { + widgetMobileBatteryEnabled = enabled + if (enabled) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver( + PhoneBatteryReceiver, + phoneBatteryIntentFilter, + RECEIVER_EXPORTED + ) + } else { + registerReceiver(PhoneBatteryReceiver, phoneBatteryIntentFilter) + } + } catch (e: Exception) { + e.printStackTrace() + } + } else { + try { + unregisterReceiver(PhoneBatteryReceiver) + } catch (e: Exception) { + e.printStackTrace() + } + } + updateBatteryWidget() + } @SuppressLint("MissingPermission") fun scanForAirPods(bluetoothAdapter: BluetoothAdapter): Flow> = callbackFlow { val bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner @@ -295,44 +440,85 @@ class AirPodsService: Service() { val widgetIds = appWidgetManager.getAppWidgetIds(componentName) val remoteViews = RemoteViews(packageName, R.layout.battery_widget).also { + val leftBattery = batteryNotification.getBattery().find { it.component == BatteryComponent.LEFT } + val rightBattery = batteryNotification.getBattery().find { it.component == BatteryComponent.RIGHT } + val caseBattery = batteryNotification.getBattery().find { it.component == BatteryComponent.CASE } + it.setTextViewText( R.id.left_battery_widget, - batteryNotification.getBattery().find { it.component == BatteryComponent.LEFT }?.let { - "${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%" + leftBattery?.let { + "${it.level}%" } ?: "" ) it.setProgressBar( R.id.left_battery_progress, 100, - batteryNotification.getBattery().find { it.component == BatteryComponent.LEFT }?.level ?: 0, + leftBattery?.level ?: 0, false ) + it.setViewVisibility( + R.id.left_charging_icon, + if (leftBattery?.status == BatteryStatus.CHARGING) View.VISIBLE else View.GONE + ) + it.setTextViewText( R.id.right_battery_widget, - batteryNotification.getBattery().find { it.component == BatteryComponent.RIGHT }?.let { - "${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%" + rightBattery?.let { + "${it.level}%" } ?: "" ) it.setProgressBar( R.id.right_battery_progress, 100, - batteryNotification.getBattery().find { it.component == BatteryComponent.RIGHT }?.level ?: 0, + rightBattery?.level ?: 0, false ) + it.setViewVisibility( + R.id.right_charging_icon, + if (rightBattery?.status == BatteryStatus.CHARGING) View.VISIBLE else View.GONE + ) + it.setTextViewText( R.id.case_battery_widget, - batteryNotification.getBattery().find { it.component == BatteryComponent.CASE }?.let { - "${if (it.status == BatteryStatus.CHARGING) "⚡" else ""} ${it.level}%" + caseBattery?.let { + "${it.level}%" } ?: "" ) it.setProgressBar( R.id.case_battery_progress, 100, - batteryNotification.getBattery().find { it.component == BatteryComponent.CASE }?.level ?: 0, + caseBattery?.level ?: 0, false ) + it.setViewVisibility( + R.id.case_charging_icon, + if (caseBattery?.status == BatteryStatus.CHARGING) View.VISIBLE else View.GONE + ) + + it.setViewVisibility( + R.id.phone_battery_widget_container, + if (widgetMobileBatteryEnabled) View.VISIBLE else View.GONE + ) + if (widgetMobileBatteryEnabled) { + val batteryManager = getSystemService(BatteryManager::class.java) + val batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + val charging = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS) == BatteryManager.BATTERY_STATUS_CHARGING + it.setTextViewText( + R.id.phone_battery_widget, + "$batteryLevel%" + ) + it.setViewVisibility( + R.id.phone_charging_icon, + if (charging) View.VISIBLE else View.GONE + ) + it.setProgressBar( + R.id.phone_battery_progress, + 100, + batteryLevel, + false + ) + } } - Log.d("AirPodsService", "Updating battery widget") appWidgetManager.updateAppWidget(widgetIds, remoteViews) } @@ -397,7 +583,7 @@ class AirPodsService: Service() { Log.d("AirPodsService", "Service started") ServiceManager.setService(this) startForegroundNotification() - + Log.d("AirPodsService", "Initializing CrossDevice") CrossDevice.init(this) Log.d("AirPodsService", "CrossDevice initialized") @@ -415,12 +601,6 @@ class AirPodsService: Service() { addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED") } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - registerReceiver(bluetoothReceiver, serviceIntentFilter, RECEIVER_EXPORTED) - } else { - registerReceiver(bluetoothReceiver, serviceIntentFilter) - } - connectionReceiver = object: BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED) { @@ -432,8 +612,8 @@ class AirPodsService: Service() { val name = this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE) .getString("name", device?.name) if (this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE).getString("name", null) == null) { - this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE).edit() - .putString("name", name).apply() + this@AirPodsService.getSharedPreferences("settings", MODE_PRIVATE).edit { + putString("name", name)} } Log.d("AirPodsQuickSwitchServices", CrossDevice.isAvailable.toString()) if (!CrossDevice.checkAirPodsConnectionStatus()) { @@ -444,8 +624,7 @@ class AirPodsService: Service() { macAddress = device!!.address updateNotificationContent(true, name.toString(), batteryNotification.getBattery()) } - } - else if (intent?.action == AirPodsNotifications.Companion.AIRPODS_DISCONNECTED) { + } else if (intent?.action == AirPodsNotifications.Companion.AIRPODS_DISCONNECTED) { device = null isConnectedLocally = false popupShown = false @@ -454,16 +633,28 @@ class AirPodsService: Service() { } } + val deviceIntentFilter = IntentFilter().apply { addAction(AirPodsNotifications.Companion.AIRPODS_CONNECTION_DETECTED) addAction(AirPodsNotifications.Companion.AIRPODS_DISCONNECTED) } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { registerReceiver(connectionReceiver, deviceIntentFilter, RECEIVER_EXPORTED) + registerReceiver(bluetoothReceiver, serviceIntentFilter, RECEIVER_EXPORTED) } else { registerReceiver(connectionReceiver, deviceIntentFilter) + registerReceiver(bluetoothReceiver, serviceIntentFilter) } + widgetMobileBatteryEnabled = getSharedPreferences("settings", MODE_PRIVATE).getBoolean("show_phone_battery_in_widget", true) + if (widgetMobileBatteryEnabled) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(PhoneBatteryReceiver, phoneBatteryIntentFilter, RECEIVER_EXPORTED) + } else { + registerReceiver(PhoneBatteryReceiver, phoneBatteryIntentFilter) + } + } val bluetoothAdapter = getSystemService(BluetoothManager::class.java).adapter if (bluetoothAdapter.isEnabled) { CoroutineScope(Dispatchers.IO).launch { @@ -801,6 +992,15 @@ class AirPodsService: Service() { } else { connectAudio(this@AirPodsService, device) } +// setBatteryLevels( +// batteryNotification.getBattery()[0].status == 1, +// batteryNotification.getBattery()[0].level, +// batteryNotification.getBattery()[1].status == 1, +// batteryNotification.getBattery()[1].level, +// batteryNotification.getBattery()[2].status == 1, +// batteryNotification.getBattery()[2].level, +// device +// ) } else if (conversationAwarenessNotification.isConversationalAwarenessData( data ) diff --git a/android/app/src/main/java/me/kavishdevar/aln/BatteryWidget.kt b/android/app/src/main/java/me/kavishdevar/aln/widgets/BatteryWidget.kt similarity index 56% rename from android/app/src/main/java/me/kavishdevar/aln/BatteryWidget.kt rename to android/app/src/main/java/me/kavishdevar/aln/widgets/BatteryWidget.kt index 724d222..72fa986 100644 --- a/android/app/src/main/java/me/kavishdevar/aln/BatteryWidget.kt +++ b/android/app/src/main/java/me/kavishdevar/aln/widgets/BatteryWidget.kt @@ -17,15 +17,21 @@ */ -package me.kavishdevar.aln +package me.kavishdevar.aln.widgets +import android.app.PendingIntent import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetProvider import android.content.Context +import android.content.Intent +import android.graphics.Canvas +import android.util.Log import android.widget.RemoteViews +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.core.graphics.createBitmap +import me.kavishdevar.aln.MainActivity +import me.kavishdevar.aln.R import me.kavishdevar.aln.services.ServiceManager -import me.kavishdevar.aln.utils.BatteryComponent -import me.kavishdevar.aln.utils.BatteryStatus class BatteryWidget : AppWidgetProvider() { override fun onUpdate( @@ -33,7 +39,6 @@ class BatteryWidget : AppWidgetProvider() { appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { - // There may be multiple widgets active, so update all of them for (appWidgetId in appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId) } @@ -44,40 +49,19 @@ class BatteryWidget : AppWidgetProvider() { } } +@OptIn(ExperimentalMaterial3Api::class) internal fun updateAppWidget( context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int ) { val service = ServiceManager.getService() - val batteryList = service?.batteryNotification?.getBattery() - val views = RemoteViews(context.packageName, R.layout.battery_widget) - 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 { - // "" - // } - } ?: "") + service?.updateBatteryWidget() + + val openActivityIntent = PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + views.setOnClickPendingIntent(R.id.battery_widget, openActivityIntent) appWidgetManager.updateAppWidget(appWidgetId, views) } \ No newline at end of file diff --git a/android/app/src/main/res/drawable/blur_background.xml b/android/app/src/main/res/drawable/blur_background.xml deleted file mode 100644 index 31f0cf3..0000000 --- a/android/app/src/main/res/drawable/blur_background.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/drawable/button_background.xml b/android/app/src/main/res/drawable/button_background.xml new file mode 100644 index 0000000..5af4447 --- /dev/null +++ b/android/app/src/main/res/drawable/button_background.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/circular_progress_bar.xml b/android/app/src/main/res/drawable/circular_progress_bar.xml index 420cf39..c598e4d 100644 --- a/android/app/src/main/res/drawable/circular_progress_bar.xml +++ b/android/app/src/main/res/drawable/circular_progress_bar.xml @@ -1,15 +1,13 @@ - - + + - \ No newline at end of file + diff --git a/android/app/src/main/res/drawable/ic_power.xml b/android/app/src/main/res/drawable/ic_power.xml new file mode 100644 index 0000000..2aeb2ed --- /dev/null +++ b/android/app/src/main/res/drawable/ic_power.xml @@ -0,0 +1,15 @@ + + + + diff --git a/android/app/src/main/res/drawable/shape.xml b/android/app/src/main/res/drawable/popup_shape.xml similarity index 77% rename from android/app/src/main/res/drawable/shape.xml rename to android/app/src/main/res/drawable/popup_shape.xml index be9dd16..2349064 100644 --- a/android/app/src/main/res/drawable/shape.xml +++ b/android/app/src/main/res/drawable/popup_shape.xml @@ -1,10 +1,10 @@ + android:shape="rectangle"> + android:color="@color/popup_background"> + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/smartphone.xml b/android/app/src/main/res/drawable/smartphone.xml new file mode 100644 index 0000000..1d8a340 --- /dev/null +++ b/android/app/src/main/res/drawable/smartphone.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/android/app/src/main/res/drawable/widget_background.xml b/android/app/src/main/res/drawable/widget_background.xml new file mode 100644 index 0000000..b9414e0 --- /dev/null +++ b/android/app/src/main/res/drawable/widget_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/layout/battery_widget.xml b/android/app/src/main/res/layout/battery_widget.xml index 3494165..a5110e0 100644 --- a/android/app/src/main/res/layout/battery_widget.xml +++ b/android/app/src/main/res/layout/battery_widget.xml @@ -2,28 +2,106 @@ xmlns:tools="http://schemas.android.com/tools" style="@style/Widget.ALN.AppWidget.Container" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" + android:layout_margin="0dp" + android:padding="0dp" android:id="@+id/battery_widget" android:theme="@style/Theme.ALN.AppWidgetContainer" - android:background="@drawable/blur_background"> + android:background="@drawable/widget_background"> + android:id="@android:id/background" + android:layout_gravity="center"> + + + + + + + + + + + + @@ -54,13 +146,24 @@ + + @@ -81,8 +195,10 @@ android:id="@+id/right_battery_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="16sp" - android:textColor="@color/popup_text" + android:textSize="24sp" + android:textFontWeight="300" + android:textColor="@color/white" + android:fontFamily="@font/sf_pro" android:gravity="center" android:text="Right" tools:ignore="HardcodedText" /> @@ -91,13 +207,24 @@ + + @@ -118,9 +256,11 @@ android:id="@+id/case_battery_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="16sp" - android:textColor="@color/popup_text" + android:textSize="24sp" + android:textColor="@color/white" android:gravity="center" + android:fontFamily="@font/sf_pro" + android:textFontWeight="300" android:text="Case" tools:ignore="HardcodedText" /> diff --git a/android/app/src/main/res/layout/popup_window.xml b/android/app/src/main/res/layout/popup_window.xml index 0739664..c470317 100644 --- a/android/app/src/main/res/layout/popup_window.xml +++ b/android/app/src/main/res/layout/popup_window.xml @@ -7,7 +7,7 @@ android:layout_margin="16.dp" android:id="@+id/linear_layout" android:orientation="vertical" - android:background="@drawable/shape"> + android:background="@drawable/popup_shape"> \ No newline at end of file diff --git a/android/app/src/main/res/xml/battery_widget_info.xml b/android/app/src/main/res/xml/battery_widget_info.xml index 7fcdc15..221ebf9 100644 --- a/android/app/src/main/res/xml/battery_widget_info.xml +++ b/android/app/src/main/res/xml/battery_widget_info.xml @@ -1,14 +1,16 @@ \ No newline at end of file + android:widgetCategory="home_screen|keyguard" + tools:ignore="UnusedAttribute" /> \ No newline at end of file