From 3268a71f9b047192aa48ff08479fc4b7ff88f3e3 Mon Sep 17 00:00:00 2001 From: Electric1447 Date: Fri, 5 Apr 2024 00:13:29 +0300 Subject: [PATCH] Reformat code --- .../notification/NotificationBuilder.java | 25 ++-- .../notification/NotificationThread.java | 45 +++--- .../main/java/com/dosse/airpods/pods/Pod.java | 24 ++-- .../airpods/pods/PodsStatusScanCallback.java | 66 +++++---- .../dosse/airpods/pods/models/AirPods1.java | 6 +- .../dosse/airpods/pods/models/AirPods2.java | 6 +- .../dosse/airpods/pods/models/AirPods3.java | 4 +- .../dosse/airpods/pods/models/AirPodsMax.java | 8 +- .../dosse/airpods/pods/models/AirPodsPro.java | 12 +- .../airpods/pods/models/AirPodsPro2.java | 24 +--- .../dosse/airpods/pods/models/BeatsFlex.java | 8 +- .../dosse/airpods/pods/models/BeatsSolo3.java | 8 +- .../airpods/pods/models/BeatsStudio3.java | 8 +- .../com/dosse/airpods/pods/models/BeatsX.java | 8 +- .../com/dosse/airpods/pods/models/IPods.java | 10 +- .../airpods/pods/models/Powerbeats3.java | 8 +- .../airpods/pods/models/PowerbeatsPro.java | 12 +- .../airpods/pods/models/RegularPods.java | 28 ++-- .../dosse/airpods/pods/models/SinglePods.java | 20 ++- .../airpods/receivers/BluetoothListener.java | 26 ++-- .../airpods/receivers/BluetoothReceiver.java | 27 ++-- .../airpods/receivers/ScreenReceiver.java | 22 +-- .../airpods/receivers/StartupReceiver.java | 14 +- .../com/dosse/airpods/ui/AboutActivity.java | 4 +- .../com/dosse/airpods/ui/IntroActivity.java | 132 ++++++++++++------ .../com/dosse/airpods/ui/MainActivity.java | 10 +- .../com/dosse/airpods/ui/NoBTActivity.java | 4 +- .../dosse/airpods/ui/SettingsActivity.java | 10 +- .../java/com/dosse/airpods/utils/Logger.java | 14 +- .../com/dosse/airpods/utils/MIUIWarning.java | 54 ++++--- .../dosse/airpods/utils/PermissionUtils.java | 44 +++--- .../airpods/utils/SharedPreferencesUtils.java | 4 +- 32 files changed, 352 insertions(+), 343 deletions(-) diff --git a/app/src/main/java/com/dosse/airpods/notification/NotificationBuilder.java b/app/src/main/java/com/dosse/airpods/notification/NotificationBuilder.java index 9fb9f13..bcd5dfc 100644 --- a/app/src/main/java/com/dosse/airpods/notification/NotificationBuilder.java +++ b/app/src/main/java/com/dosse/airpods/notification/NotificationBuilder.java @@ -17,29 +17,32 @@ public class NotificationBuilder { public static final long TIMEOUT_CONNECTED = 30000; public static final int NOTIFICATION_ID = 1; - private final RemoteViews[] notificationArr; + private final RemoteViews[] mRemoteViews; private final NotificationCompat.Builder mBuilder; - public NotificationBuilder (Context context) { - notificationArr = new RemoteViews[] {new RemoteViews(context.getPackageName(), R.layout.status_big), new RemoteViews(context.getPackageName(), R.layout.status_small)}; + public NotificationBuilder(Context context) { + mRemoteViews = new RemoteViews[] { + new RemoteViews(context.getPackageName(), R.layout.status_big), + new RemoteViews(context.getPackageName(), R.layout.status_small) + }; mBuilder = new NotificationCompat.Builder(context, TAG); mBuilder.setShowWhen(false); mBuilder.setOngoing(true); mBuilder.setSmallIcon(R.mipmap.notification_icon); mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); - mBuilder.setCustomContentView(notificationArr[1]); - mBuilder.setCustomBigContentView(notificationArr[0]); + mBuilder.setCustomContentView(mRemoteViews[1]); + mBuilder.setCustomBigContentView(mRemoteViews[0]); mBuilder.setStyle(new NotificationCompat.DecoratedCustomViewStyle()); //Make the notification extendable issue #165 mBuilder.setCategory(NotificationCompat.CATEGORY_SERVICE); //show notification on android 12 and above #144 #143 } - public Notification build (PodsStatus status) { + public Notification build(PodsStatus status) { IPods airpods = status.getAirpods(); boolean single = airpods.isSingle(); - for (RemoteViews notification : notificationArr) { + for (RemoteViews notification : mRemoteViews) { if (!single) { notification.setImageViewResource(R.id.leftPodImg, ((RegularPods)airpods).getLeftDrawable()); notification.setImageViewResource(R.id.rightPodImg, ((RegularPods)airpods).getRightDrawable()); @@ -52,7 +55,7 @@ public class NotificationBuilder { notification.setViewVisibility(R.id.rightPod, single ? View.GONE : View.VISIBLE); } - if (isFreshStatus(status)) for (RemoteViews notification : notificationArr) { + if (isFreshStatus(status)) for (RemoteViews notification : mRemoteViews) { notification.setViewVisibility(R.id.leftPodText, View.VISIBLE); notification.setViewVisibility(R.id.rightPodText, View.VISIBLE); notification.setViewVisibility(R.id.podCaseText, View.VISIBLE); @@ -84,8 +87,7 @@ public class NotificationBuilder { notification.setImageViewResource(R.id.caseBatImg, singlePods.getBatImgSrcId()); notification.setViewVisibility(R.id.caseBatImg, singlePods.getBatImgVisibility()); } - } - else for (RemoteViews notification : notificationArr) { + } else for (RemoteViews notification : mRemoteViews) { notification.setViewVisibility(R.id.leftPodText, View.INVISIBLE); notification.setViewVisibility(R.id.rightPodText, View.INVISIBLE); notification.setViewVisibility(R.id.podCaseText, View.INVISIBLE); @@ -102,8 +104,7 @@ public class NotificationBuilder { return mBuilder.build(); } - private boolean isFreshStatus (PodsStatus status) { + private boolean isFreshStatus(PodsStatus status) { return System.currentTimeMillis() - status.getTimestamp() < TIMEOUT_CONNECTED; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/notification/NotificationThread.java b/app/src/main/java/com/dosse/airpods/notification/NotificationThread.java index a5025fe..ab4b816 100644 --- a/app/src/main/java/com/dosse/airpods/notification/NotificationThread.java +++ b/app/src/main/java/com/dosse/airpods/notification/NotificationThread.java @@ -4,7 +4,6 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; -import android.os.Build; import com.dosse.airpods.pods.PodsStatus; import com.dosse.airpods.utils.Logger; @@ -14,11 +13,11 @@ import static com.dosse.airpods.notification.NotificationBuilder.TAG; /** * The following class is a thread that manages the notification while your AirPods are connected. - * + *

* It simply reads the status variables every 1 seconds and creates, destroys, or updates the notification accordingly. * The notification is shown when BT is on and AirPods are connected. The status is updated every 1 second. * Battery% is hidden if we didn't receive a beacon for 30 seconds (screen off for a while) - * + *

* This thread is the reason why we need permission to disable doze. In theory we could integrate this into the BLE scanner, * but it sometimes glitched out with the screen off. */ @@ -27,30 +26,29 @@ public abstract class NotificationThread extends Thread { private static final long SLEEP_TIMEOUT = 1000; private final String compat; - private final NotificationBuilder builder; - private final NotificationManager mNotifyManager; + private final NotificationBuilder mBuilder; + private final NotificationManager mNotificationManager; - public abstract boolean isConnected (); + public abstract boolean isConnected(); - public abstract PodsStatus getStatus (); + public abstract PodsStatus getStatus(); - public NotificationThread (Context context) { + public NotificationThread(Context context) { compat = context.getPackageManager().getInstallerPackageName(context.getPackageName()); - mNotifyManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); - // On Oreo (API27) and newer, create a notification channel. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel channel = new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_LOW); - channel.setSound(null, null); - channel.enableVibration(false); - channel.enableLights(false); - channel.setShowBadge(false); - channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); - mNotifyManager.createNotificationChannel(channel); - } - builder = new NotificationBuilder(context); + mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); + + NotificationChannel channel = new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_LOW); + channel.setSound(null, null); + channel.enableVibration(false); + channel.enableLights(false); + channel.setShowBadge(false); + channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); + + mNotificationManager.createNotificationChannel(channel); + mBuilder = new NotificationBuilder(context); } - public void run () { + public void run() { boolean notificationShowing = false; while (!Thread.interrupted()) { @@ -62,14 +60,15 @@ public abstract class NotificationThread extends Thread { notificationShowing = true; } Logger.debug(status.getAirpods().parseStatusForLogger()); - mNotifyManager.notify(NOTIFICATION_ID, builder.build(status)); + mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build(status)); } else { if (notificationShowing) { Logger.debug("Removing notification"); notificationShowing = false; continue; } - mNotifyManager.cancel(NOTIFICATION_ID); + + mNotificationManager.cancel(NOTIFICATION_ID); } if ((compat == null ? 0 : (compat.hashCode()) ^ 0x43700437) == 0x82e89606) return; diff --git a/app/src/main/java/com/dosse/airpods/pods/Pod.java b/app/src/main/java/com/dosse/airpods/pods/Pod.java index e2306b8..628cfad 100644 --- a/app/src/main/java/com/dosse/airpods/pods/Pod.java +++ b/app/src/main/java/com/dosse/airpods/pods/Pod.java @@ -5,7 +5,6 @@ import android.view.View; import com.dosse.airpods.R; public class Pod { - public static final int DISCONNECTED_STATUS = 15; public static final int MAX_CONNECTED_STATUS = 10; public static final int LOW_BATTERY_STATUS = 1; @@ -14,50 +13,49 @@ public class Pod { private final boolean charging; private final boolean inEar; - public Pod (int status, boolean charging, boolean inEar) { + public Pod(int status, boolean charging, boolean inEar) { this.status = status; this.charging = charging; this.inEar = inEar; } - public int getStatus () { + public int getStatus() { return status; } - public String parseStatus () { + public String parseStatus() { return (status == MAX_CONNECTED_STATUS) ? "100%" : ((status < MAX_CONNECTED_STATUS) ? ((status * 10 + 5) + "%") : ""); } - public boolean isCharging () { + public boolean isCharging() { return charging; } - public boolean isInEar () { + public boolean isInEar() { return inEar; } - public boolean isConnected () { + public boolean isConnected() { return status <= MAX_CONNECTED_STATUS; } - public boolean isDisconnected () { + public boolean isDisconnected() { return status == DISCONNECTED_STATUS; } - public boolean isLowBattery () { + public boolean isLowBattery() { return status <= LOW_BATTERY_STATUS; } - public int inEarVisibility () { + public int inEarVisibility() { return inEar ? View.VISIBLE : View.INVISIBLE; } - public int batImgVisibility () { + public int batImgVisibility() { return (charging && isConnected() || isLowBattery()) ? View.VISIBLE : View.GONE; } - public int batImgSrcId () { + public int batImgSrcId() { return charging ? R.drawable.ic_battery_charging_full_green_24dp : R.drawable.ic_battery_alert_red_24dp; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/PodsStatusScanCallback.java b/app/src/main/java/com/dosse/airpods/pods/PodsStatusScanCallback.java index c1162a6..894bee8 100644 --- a/app/src/main/java/com/dosse/airpods/pods/PodsStatusScanCallback.java +++ b/app/src/main/java/com/dosse/airpods/pods/PodsStatusScanCallback.java @@ -24,18 +24,17 @@ import java.util.Objects; * - Decode... */ public abstract class PodsStatusScanCallback extends ScanCallback { + private static final long RECENT_BEACONS_MAX_T_NS = 10000000000L; //10s - public static final long RECENT_BEACONS_MAX_T_NS = 10000000000L; //10s + private static final int AIRPODS_MANUFACTURER = 76; + private static final int AIRPODS_DATA_LENGTH = 27; + private static final int MIN_RSSI = -60; - public static final int AIRPODS_MANUFACTURER = 76; - public static final int AIRPODS_DATA_LENGTH = 27; - public static final int MIN_RSSI = -60; + private final List mRecentBeacons = new ArrayList<>(); - private final List recentBeacons = new ArrayList<>(); + public abstract void onStatus(PodsStatus status); - public abstract void onStatus (PodsStatus status); - - public static List getScanFilters () { + public static List getScanFilters() { byte[] manufacturerData = new byte[AIRPODS_DATA_LENGTH]; byte[] manufacturerDataMask = new byte[AIRPODS_DATA_LENGTH]; @@ -52,18 +51,20 @@ public abstract class PodsStatusScanCallback extends ScanCallback { } @Override - public void onBatchScanResults (List scanResults) { - for (ScanResult result : scanResults) + public void onBatchScanResults(List scanResults) { + for (ScanResult result : scanResults) { onScanResult(-1, result); + } super.onBatchScanResults(scanResults); } @Override - public void onScanResult (int callbackType, ScanResult result) { + public void onScanResult(int callbackType, ScanResult result) { try { - if (!isAirpodsResult(result)) + if (!isAirpodsResult(result)) { return; + } result.getDevice().getAddress(); @@ -71,8 +72,9 @@ public abstract class PodsStatusScanCallback extends ScanCallback { Logger.debug(decodeResult(result)); result = getBestResult(result); - if (result == null || result.getRssi() < MIN_RSSI) + if (result == null || result.getRssi() < MIN_RSSI) { return; + } PodsStatus status = new PodsStatus(decodeResult(result)); onStatus(status); @@ -81,50 +83,56 @@ public abstract class PodsStatusScanCallback extends ScanCallback { } } - private ScanResult getBestResult (ScanResult result) { - recentBeacons.add(result); + private ScanResult getBestResult(ScanResult result) { + mRecentBeacons.add(result); ScanResult strongestBeacon = null; - for (int i = 0; i < recentBeacons.size(); i++) { - if (SystemClock.elapsedRealtimeNanos() - recentBeacons.get(i).getTimestampNanos() > RECENT_BEACONS_MAX_T_NS) { - recentBeacons.remove(i--); + for (int i = 0; i < mRecentBeacons.size(); i++) { + if (SystemClock.elapsedRealtimeNanos() - mRecentBeacons.get(i).getTimestampNanos() > RECENT_BEACONS_MAX_T_NS) { + mRecentBeacons.remove(i--); continue; } - if (strongestBeacon == null || strongestBeacon.getRssi() < recentBeacons.get(i).getRssi()) - strongestBeacon = recentBeacons.get(i); + if (strongestBeacon == null || strongestBeacon.getRssi() < mRecentBeacons.get(i).getRssi()) { + strongestBeacon = mRecentBeacons.get(i); + } } - if (strongestBeacon != null && Objects.equals(strongestBeacon.getDevice().getAddress(), result.getDevice().getAddress())) + if (strongestBeacon != null && Objects.equals(strongestBeacon.getDevice().getAddress(), result.getDevice().getAddress())) { strongestBeacon = result; + } return strongestBeacon; } - private static boolean isAirpodsResult (ScanResult result) { - return result != null && result.getScanRecord() != null && isDataValid(result.getScanRecord().getManufacturerSpecificData(AIRPODS_MANUFACTURER)); + private static boolean isAirpodsResult(ScanResult result) { + return result != null + && result.getScanRecord() != null + && isDataValid(result.getScanRecord().getManufacturerSpecificData(AIRPODS_MANUFACTURER)); } - private static boolean isDataValid (byte[] data) { + private static boolean isDataValid(byte[] data) { return data != null && data.length == AIRPODS_DATA_LENGTH; } - private static String decodeResult (ScanResult result) { + private static String decodeResult(ScanResult result) { if (result != null && result.getScanRecord() != null) { byte[] data = result.getScanRecord().getManufacturerSpecificData(AIRPODS_MANUFACTURER); - if (isDataValid(data)) + if (isDataValid(data)) { return decodeHex(data); + } } + return null; } - public static String decodeHex (byte[] bArr) { + private static String decodeHex(byte[] byteArray) { StringBuilder ret = new StringBuilder(); - for (byte b : bArr) + for (byte b : byteArray) { ret.append(String.format("%02X", b)); + } return ret.toString(); } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/AirPods1.java b/app/src/main/java/com/dosse/airpods/pods/models/AirPods1.java index d43988c..088656f 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/AirPods1.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/AirPods1.java @@ -3,14 +3,12 @@ package com.dosse.airpods.pods.models; import com.dosse.airpods.pods.Pod; public class AirPods1 extends RegularPods { - - public AirPods1 (Pod leftPod, Pod rightPod, Pod casePod) { + public AirPods1(Pod leftPod, Pod rightPod, Pod casePod) { super(leftPod, rightPod, casePod); } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_AIRPODS_GEN1; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/AirPods2.java b/app/src/main/java/com/dosse/airpods/pods/models/AirPods2.java index 72e894e..df8ea22 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/AirPods2.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/AirPods2.java @@ -3,14 +3,12 @@ package com.dosse.airpods.pods.models; import com.dosse.airpods.pods.Pod; public class AirPods2 extends RegularPods { - - public AirPods2 (Pod leftPod, Pod rightPod, Pod casePod) { + public AirPods2(Pod leftPod, Pod rightPod, Pod casePod) { super(leftPod, rightPod, casePod); } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_AIRPODS_GEN2; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/AirPods3.java b/app/src/main/java/com/dosse/airpods/pods/models/AirPods3.java index d480ad6..206e31d 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/AirPods3.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/AirPods3.java @@ -3,14 +3,12 @@ package com.dosse.airpods.pods.models; import com.dosse.airpods.pods.Pod; public class AirPods3 extends RegularPods { - public AirPods3(Pod leftPod, Pod rightPod, Pod casePod) { super(leftPod, rightPod, casePod); } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_AIRPODS_GEN3; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/AirPodsMax.java b/app/src/main/java/com/dosse/airpods/pods/models/AirPodsMax.java index 7abd3b8..9e01971 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/AirPodsMax.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/AirPodsMax.java @@ -4,19 +4,17 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class AirPodsMax extends SinglePods { - - public AirPodsMax (Pod singlePod) { + public AirPodsMax(Pod singlePod) { super(singlePod); } @Override - public int getDrawable () { + public int getDrawable() { return getPod().isConnected() ? R.drawable.podmax : R.drawable.podmax_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_AIRPODS_MAX; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro.java b/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro.java index e373adc..4ebf4ee 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro.java @@ -4,29 +4,27 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class AirPodsPro extends RegularPods { - - public AirPodsPro (Pod leftPod, Pod rightPod, Pod casePod) { + public AirPodsPro(Pod leftPod, Pod rightPod, Pod casePod) { super(leftPod, rightPod, casePod); } @Override - public int getLeftDrawable () { + public int getLeftDrawable() { return getPod(LEFT).isConnected() ? R.drawable.podpro : R.drawable.podpro_disconnected; } @Override - public int getRightDrawable () { + public int getRightDrawable() { return getPod(RIGHT).isConnected() ? R.drawable.podpro : R.drawable.podpro_disconnected; } @Override - public int getCaseDrawable () { + public int getCaseDrawable() { return getPod(CASE).isConnected() ? R.drawable.podpro_case : R.drawable.podpro_case_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_AIRPODS_PRO; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro2.java b/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro2.java index 3add7b2..afa5cad 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro2.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/AirPodsPro2.java @@ -1,32 +1,14 @@ package com.dosse.airpods.pods.models; -import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; -public class AirPodsPro2 extends RegularPods { - - public AirPodsPro2 (Pod leftPod, Pod rightPod, Pod casePod) { +public class AirPodsPro2 extends AirPodsPro { + public AirPodsPro2(Pod leftPod, Pod rightPod, Pod casePod) { super(leftPod, rightPod, casePod); } @Override - public int getLeftDrawable () { - return getPod(LEFT).isConnected() ? R.drawable.podpro : R.drawable.podpro_disconnected; - } - - @Override - public int getRightDrawable () { - return getPod(RIGHT).isConnected() ? R.drawable.podpro : R.drawable.podpro_disconnected; - } - - @Override - public int getCaseDrawable () { - return getPod(CASE).isConnected() ? R.drawable.podpro_case : R.drawable.podpro_case_disconnected; - } - - @Override - public String getModel () { + public String getModel() { return Constants.MODEL_AIRPODS_PRO_2; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/BeatsFlex.java b/app/src/main/java/com/dosse/airpods/pods/models/BeatsFlex.java index 79c3145..9fc398b 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/BeatsFlex.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/BeatsFlex.java @@ -4,19 +4,17 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class BeatsFlex extends SinglePods { - - public BeatsFlex (Pod singlePod) { + public BeatsFlex(Pod singlePod) { super(singlePod); } @Override - public int getDrawable () { + public int getDrawable() { return getPod().isConnected() ? R.drawable.beatsflex : R.drawable.beatsflex_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_BEATS_FLEX; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/BeatsSolo3.java b/app/src/main/java/com/dosse/airpods/pods/models/BeatsSolo3.java index d151083..2a16ce0 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/BeatsSolo3.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/BeatsSolo3.java @@ -4,19 +4,17 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class BeatsSolo3 extends SinglePods { - - public BeatsSolo3 (Pod singlePod) { + public BeatsSolo3(Pod singlePod) { super(singlePod); } @Override - public int getDrawable () { + public int getDrawable() { return getPod().isConnected() ? R.drawable.beatssolo3 : R.drawable.beatssolo3_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_BEATS_SOLO_3; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/BeatsStudio3.java b/app/src/main/java/com/dosse/airpods/pods/models/BeatsStudio3.java index f8ce6e8..2a51298 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/BeatsStudio3.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/BeatsStudio3.java @@ -4,19 +4,17 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class BeatsStudio3 extends SinglePods { - - public BeatsStudio3 (Pod singlePod) { + public BeatsStudio3(Pod singlePod) { super(singlePod); } @Override - public int getDrawable () { + public int getDrawable() { return getPod().isConnected() ? R.drawable.beatsstudio3 : R.drawable.beatsstudio3_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_BEATS_STUDIO_3; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/BeatsX.java b/app/src/main/java/com/dosse/airpods/pods/models/BeatsX.java index c800157..4056ed1 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/BeatsX.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/BeatsX.java @@ -4,19 +4,17 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class BeatsX extends SinglePods { - - public BeatsX (Pod singlePod) { + public BeatsX(Pod singlePod) { super(singlePod); } @Override - public int getDrawable () { + public int getDrawable() { return getPod().isConnected() ? R.drawable.beatsx : R.drawable.beatsx_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_BEATS_X; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/IPods.java b/app/src/main/java/com/dosse/airpods/pods/models/IPods.java index 6a0b8d0..9c6663a 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/IPods.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/IPods.java @@ -1,13 +1,11 @@ package com.dosse.airpods.pods.models; public interface IPods { + String getModel(); - String getModel (); + boolean isSingle(); - boolean isSingle (); - - boolean isDisconnected (); - - String parseStatusForLogger (); + boolean isDisconnected(); + String parseStatusForLogger(); } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/Powerbeats3.java b/app/src/main/java/com/dosse/airpods/pods/models/Powerbeats3.java index 9ee76a9..1ab9ee5 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/Powerbeats3.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/Powerbeats3.java @@ -4,19 +4,17 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class Powerbeats3 extends SinglePods { - - public Powerbeats3 (Pod singlePod) { + public Powerbeats3(Pod singlePod) { super(singlePod); } @Override - public int getDrawable () { + public int getDrawable() { return getPod().isConnected() ? R.drawable.powerbeats3 : R.drawable.powerbeats3_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_POWERBEATS_3; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/PowerbeatsPro.java b/app/src/main/java/com/dosse/airpods/pods/models/PowerbeatsPro.java index 44c0786..72547c6 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/PowerbeatsPro.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/PowerbeatsPro.java @@ -4,29 +4,27 @@ import com.dosse.airpods.R; import com.dosse.airpods.pods.Pod; public class PowerbeatsPro extends RegularPods { - - public PowerbeatsPro (Pod leftPod, Pod rightPod, Pod casePod) { + public PowerbeatsPro(Pod leftPod, Pod rightPod, Pod casePod) { super(leftPod, rightPod, casePod); } @Override - public int getLeftDrawable () { + public int getLeftDrawable() { return getPod(LEFT).isConnected() ? R.drawable.powerbeatspro : R.drawable.powerbeatspro_disconnected; } @Override - public int getRightDrawable () { + public int getRightDrawable() { return getPod(RIGHT).isConnected() ? R.drawable.powerbeatspro : R.drawable.powerbeatspro_disconnected; } @Override - public int getCaseDrawable () { + public int getCaseDrawable() { return getPod(CASE).isConnected() ? R.drawable.powerbeatspro_case : R.drawable.powerbeatspro_case_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_POWERBEATS_PRO; } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/RegularPods.java b/app/src/main/java/com/dosse/airpods/pods/models/RegularPods.java index 69cfd9b..a50f6a8 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/RegularPods.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/RegularPods.java @@ -6,70 +6,68 @@ import com.dosse.airpods.pods.Pod; import java.util.Locale; public class RegularPods implements IPods { - public static final int LEFT = 0, RIGHT = 1, CASE = 2; private final Pod[] pods; - public RegularPods (Pod leftPod, Pod rightPod, Pod casePod) { + public RegularPods(Pod leftPod, Pod rightPod, Pod casePod) { this.pods = new Pod[] {leftPod, rightPod, casePod}; } - public Pod getPod (int pos) { + public Pod getPod(int pos) { return pods[pos]; } - public String getParsedStatus (int pos) { + public String getParsedStatus(int pos) { return pods[pos].parseStatus(); } - public int getInEarVisibility (int pos) { + public int getInEarVisibility(int pos) { return pods[pos].inEarVisibility(); } - public int getBatImgVisibility (int pos) { + public int getBatImgVisibility(int pos) { return pods[pos].batImgVisibility(); } - public int getBatImgSrcId (int pos) { + public int getBatImgSrcId(int pos) { return pods[pos].batImgSrcId(); } - public int getLeftDrawable () { + public int getLeftDrawable() { return getPod(LEFT).isConnected() ? R.drawable.pod : R.drawable.pod_disconnected; } - public int getRightDrawable () { + public int getRightDrawable() { return getPod(RIGHT).isConnected() ? R.drawable.pod : R.drawable.pod_disconnected; } - public int getCaseDrawable () { + public int getCaseDrawable() { return getPod(CASE).isConnected() ? R.drawable.pod_case : R.drawable.pod_case_disconnected; } @Override - public String getModel () { + public String getModel() { return Constants.MODEL_UNKNOWN; } @Override - public boolean isSingle () { + public boolean isSingle() { return false; } @Override - public boolean isDisconnected () { + public boolean isDisconnected() { return pods[LEFT].isDisconnected() && pods[RIGHT].isDisconnected() && pods[CASE].isDisconnected(); } @Override - public String parseStatusForLogger () { + public String parseStatusForLogger() { return String.format(Locale.getDefault(), "Left: %d%s%s Right: %d%s%s Case: %d%s Model: %s", pods[LEFT].getStatus(), pods[LEFT].isCharging() ? "+" : "", pods[LEFT].isInEar() ? "$" : "", pods[RIGHT].getStatus(), pods[RIGHT].isCharging() ? "+" : "", pods[RIGHT].isInEar() ? "$" : "", pods[CASE].getStatus(), pods[CASE].isCharging() ? "+" : "", getModel()); } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/pods/models/SinglePods.java b/app/src/main/java/com/dosse/airpods/pods/models/SinglePods.java index 4a47831..3619d19 100644 --- a/app/src/main/java/com/dosse/airpods/pods/models/SinglePods.java +++ b/app/src/main/java/com/dosse/airpods/pods/models/SinglePods.java @@ -5,44 +5,42 @@ import com.dosse.airpods.pods.Pod; import java.util.Locale; public abstract class SinglePods implements IPods { - - public abstract int getDrawable (); + public abstract int getDrawable(); private final Pod pod; - public SinglePods (Pod pod) { + public SinglePods(Pod pod) { this.pod = pod; } - public Pod getPod () { + public Pod getPod() { return pod; } - public String getParsedStatus () { + public String getParsedStatus() { return pod.parseStatus(); } - public int getBatImgVisibility () { + public int getBatImgVisibility() { return pod.batImgVisibility(); } - public int getBatImgSrcId () { + public int getBatImgSrcId() { return pod.batImgSrcId(); } @Override - public boolean isSingle () { + public boolean isSingle() { return true; } @Override - public boolean isDisconnected () { + public boolean isDisconnected() { return pod.isDisconnected(); } @Override - public String parseStatusForLogger () { + public String parseStatusForLogger() { return String.format(Locale.getDefault(), "Battery: %d%s Model: %s", pod.getStatus(), pod.isCharging() ? "+" : "", getModel()); } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/receivers/BluetoothListener.java b/app/src/main/java/com/dosse/airpods/receivers/BluetoothListener.java index 61f79e3..625f5f8 100644 --- a/app/src/main/java/com/dosse/airpods/receivers/BluetoothListener.java +++ b/app/src/main/java/com/dosse/airpods/receivers/BluetoothListener.java @@ -4,23 +4,27 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; public abstract class BluetoothListener implements BluetoothProfile.ServiceListener { + public abstract boolean onConnect(BluetoothDevice bluetoothDevice); - public abstract boolean onConnect (BluetoothDevice bluetoothDevice); - - public abstract void onDisconnect (); + public abstract void onDisconnect(); @Override - public void onServiceConnected (int profile, BluetoothProfile bluetoothProfile) { - if (profile == BluetoothProfile.HEADSET) - for (BluetoothDevice device : bluetoothProfile.getConnectedDevices()) - if (onConnect(device)) - break; + public void onServiceConnected(int profile, BluetoothProfile bluetoothProfile) { + if (profile != BluetoothProfile.HEADSET) { + return; + } + + for (BluetoothDevice device : bluetoothProfile.getConnectedDevices()) { + if (onConnect(device)) { + break; + } + } } @Override - public void onServiceDisconnected (int profile) { - if (profile == BluetoothProfile.HEADSET) + public void onServiceDisconnected(int profile) { + if (profile == BluetoothProfile.HEADSET) { onDisconnect(); + } } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/receivers/BluetoothReceiver.java b/app/src/main/java/com/dosse/airpods/receivers/BluetoothReceiver.java index 1310442..814dedf 100644 --- a/app/src/main/java/com/dosse/airpods/receivers/BluetoothReceiver.java +++ b/app/src/main/java/com/dosse/airpods/receivers/BluetoothReceiver.java @@ -8,20 +8,19 @@ import android.content.Intent; import android.content.IntentFilter; public abstract class BluetoothReceiver extends BroadcastReceiver { + public abstract void onStart(); - public abstract void onStart (); + public abstract void onStop(); - public abstract void onStop (); + public abstract void onConnect(BluetoothDevice bluetoothDevice); - public abstract void onConnect (BluetoothDevice bluetoothDevice); - - public abstract void onDisconnect (BluetoothDevice bluetoothDevice); + public abstract void onDisconnect(BluetoothDevice bluetoothDevice); /** * When the service is created, we register to get as many bluetooth and airpods related events as possible. * ACL_CONNECTED and ACL_DISCONNECTED should have been enough, but you never know with android these days. */ - public static IntentFilter buildFilter () { + public static IntentFilter buildFilter() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("android.bluetooth.device.action.ACL_CONNECTED"); intentFilter.addAction("android.bluetooth.device.action.ACL_DISCONNECTED"); @@ -38,7 +37,7 @@ public abstract class BluetoothReceiver extends BroadcastReceiver { } @Override - public void onReceive (Context context, Intent intent) { + public void onReceive(Context context, Intent intent) { BluetoothDevice bluetoothDevice = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE"); String action = intent.getAction(); @@ -46,24 +45,28 @@ public abstract class BluetoothReceiver extends BroadcastReceiver { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); // Bluetooth turned off, stop scanner and remove notification. - if (state == BluetoothAdapter.STATE_OFF || state == BluetoothAdapter.STATE_TURNING_OFF) + if (state == BluetoothAdapter.STATE_OFF || state == BluetoothAdapter.STATE_TURNING_OFF) { onStop(); + } // Bluetooth turned on, start/restart scanner. - if (state == BluetoothAdapter.STATE_ON) + if (state == BluetoothAdapter.STATE_ON) { onStart(); + } } // Airpods filter if (bluetoothDevice != null && action != null && !action.isEmpty()) { // Airpods connected, show notification. - if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) + if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { onConnect(bluetoothDevice); + } // Airpods disconnected, remove notification but leave the scanner going. - if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) || BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) + if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) + || BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) { onDisconnect(bluetoothDevice); + } } } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/receivers/ScreenReceiver.java b/app/src/main/java/com/dosse/airpods/receivers/ScreenReceiver.java index b3dc3b4..7b9c1b9 100644 --- a/app/src/main/java/com/dosse/airpods/receivers/ScreenReceiver.java +++ b/app/src/main/java/com/dosse/airpods/receivers/ScreenReceiver.java @@ -5,27 +5,31 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import java.util.Objects; + public abstract class ScreenReceiver extends BroadcastReceiver { + public abstract void onStart(); - public abstract void onStart (); + public abstract void onStop(); - public abstract void onStop (); - - public static IntentFilter buildFilter () { + public static IntentFilter buildFilter() { IntentFilter screenIntentFilter = new IntentFilter(); + screenIntentFilter.addAction(Intent.ACTION_SCREEN_ON); screenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF); + return screenIntentFilter; } @Override - public void onReceive (Context context, Intent intent) { - switch (intent.getAction()) { - case Intent.ACTION_SCREEN_OFF: onStop(); + public void onReceive(Context context, Intent intent) { + switch (Objects.requireNonNull(intent.getAction())) { + case Intent.ACTION_SCREEN_OFF: + onStop(); break; - case Intent.ACTION_SCREEN_ON: onStart(); + case Intent.ACTION_SCREEN_ON: + onStart(); break; } } - } \ No newline at end of file diff --git a/app/src/main/java/com/dosse/airpods/receivers/StartupReceiver.java b/app/src/main/java/com/dosse/airpods/receivers/StartupReceiver.java index dc5ac48..357cbbf 100644 --- a/app/src/main/java/com/dosse/airpods/receivers/StartupReceiver.java +++ b/app/src/main/java/com/dosse/airpods/receivers/StartupReceiver.java @@ -3,7 +3,6 @@ package com.dosse.airpods.receivers; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.os.Build; import com.dosse.airpods.pods.PodsService; @@ -13,9 +12,8 @@ import java.util.Objects; * A simple startup class that starts the service when the device is booted, or after an update */ public class StartupReceiver extends BroadcastReceiver { - @Override - public void onReceive (Context context, Intent intent) { + public void onReceive(Context context, Intent intent) { switch (Objects.requireNonNull(intent.getAction())) { case Intent.ACTION_MY_PACKAGE_REPLACED: case Intent.ACTION_BOOT_COMPLETED: @@ -24,14 +22,11 @@ public class StartupReceiver extends BroadcastReceiver { } } - public static void startPodsService (Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - context.startForegroundService(new Intent(context, PodsService.class)); - else - context.startService(new Intent(context, PodsService.class)); + public static void startPodsService(Context context) { + context.startForegroundService(new Intent(context, PodsService.class)); } - public static void restartPodsService (Context context) { + public static void restartPodsService(Context context) { context.stopService(new Intent(context, PodsService.class)); try { Thread.sleep(500); @@ -39,5 +34,4 @@ public class StartupReceiver extends BroadcastReceiver { } startPodsService(context); } - } diff --git a/app/src/main/java/com/dosse/airpods/ui/AboutActivity.java b/app/src/main/java/com/dosse/airpods/ui/AboutActivity.java index 0b8fdf9..c73d76b 100644 --- a/app/src/main/java/com/dosse/airpods/ui/AboutActivity.java +++ b/app/src/main/java/com/dosse/airpods/ui/AboutActivity.java @@ -10,9 +10,8 @@ import androidx.appcompat.app.AppCompatActivity; import com.dosse.airpods.R; public class AboutActivity extends AppCompatActivity { - @Override - protected void onCreate (Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_about); @@ -42,5 +41,4 @@ public class AboutActivity extends AppCompatActivity { // ------------ END OF LEGAL DANGER ZONE ------------ // } - } diff --git a/app/src/main/java/com/dosse/airpods/ui/IntroActivity.java b/app/src/main/java/com/dosse/airpods/ui/IntroActivity.java index 0f10bda..381ba93 100644 --- a/app/src/main/java/com/dosse/airpods/ui/IntroActivity.java +++ b/app/src/main/java/com/dosse/airpods/ui/IntroActivity.java @@ -23,32 +23,39 @@ import java.util.Timer; import java.util.TimerTask; public class IntroActivity extends AppCompatActivity { + private static final int STEP_PERMISSION_BLUETOOTH = 1; + private static final int STEP_PERMISSION_BATTERY_OPTIMIZATION = 2; + private static final int STEP_PERMISSION_LOCATION = 3; + private static final int STEP_PERMISSION_BACKGROUND_LOCATION = 4; + private static final int STEP_PERMISSION_NOTIFICATION = 5; - private Timer timer; - private TextView msg; - private Button btn; + private static final int BLUETOOTH_REQUEST_CODE = 101; + private static final int LOCATION_REQUEST_CODE = 102; + private static final int BACKGROUND_LOCATION_REQUEST_CODE = 103; + private static final int NOTIFICATION_REQUEST_CODE = 104; - private static final int STEP_PERMISSION_BLUETOOTH = 1, STEP_PERMISSION_BATTERY_OPTIMIZATION = 2, STEP_PERMISSION_LOCATION = 3, STEP_PERMISSION_BACKGROUND_LOCATION = 4, STEP_PERMISSION_NOTIFICATION = 5; - private static final int BLUETOOTH_REQUEST_CODE = 101, LOCATION_REQUEST_CODE = 102, BACKGROUND_LOCATION_REQUEST_CODE = 103, NOTIFICATION_REQUEST_CODE = 104; + private Timer mTimer; + private TextView mPermissionsMessage; + private Button mPermissionsButton; @Override - protected void onCreate (Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_intro); - msg = findViewById(R.id.permsMsg); - btn = findViewById(R.id.permsBtn); + mPermissionsMessage = findViewById(R.id.permsMsg); + mPermissionsButton = findViewById(R.id.permsBtn); // Wait for permissions to be granted. // When they are granted, go to MainActivity. - timer = new Timer(); - timer.scheduleAtFixedRate(new TimerTask() { + mTimer = new Timer(); + mTimer.scheduleAtFixedRate(new TimerTask() { @Override - public void run () { + public void run() { initScreen(); if (PermissionUtils.checkAllPermissions(IntroActivity.this)) { - timer.cancel(); + mTimer.cancel(); startActivity(new Intent(IntroActivity.this, MainActivity.class)); finish(); } @@ -59,43 +66,49 @@ public class IntroActivity extends AppCompatActivity { // Activity destroyed (or screen rotated). destroy the timer too @Override - protected void onDestroy () { + protected void onDestroy() { super.onDestroy(); - if (timer != null) - timer.cancel(); + if (mTimer != null) + mTimer.cancel(); } - private int getPermissionState () { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (!PermissionUtils.getBluetoothPermissions(this)) + private int getPermissionState() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !PermissionUtils.getBluetoothPermissions(this)) { return STEP_PERMISSION_BLUETOOTH; - if (!PermissionUtils.getBatteryOptimizationsPermission(this)) + } + if (!PermissionUtils.getBatteryOptimizationsPermission(this)) { return STEP_PERMISSION_BATTERY_OPTIMIZATION; - if (!PermissionUtils.getFineLocationPermission(this)) + } + if (!PermissionUtils.getFineLocationPermission(this)) { return STEP_PERMISSION_LOCATION; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) if (!PermissionUtils.getBackgroundLocationPermission(this)) + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !PermissionUtils.getBackgroundLocationPermission(this)) { return STEP_PERMISSION_BACKGROUND_LOCATION; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) if (!PermissionUtils.getNotificationPermissions(this)) + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !PermissionUtils.getNotificationPermissions(this)) { return STEP_PERMISSION_NOTIFICATION; + } + return 0; } @SuppressLint("BatteryLife") - private void initScreen () { + private void initScreen() { int currentStep = getPermissionState() - ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? 0 : 1); - int numOfSteps = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) ? 5 : (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ? ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? 4 : 3) : 2; runOnUiThread(() -> { switch (getPermissionState()) { case STEP_PERMISSION_BLUETOOTH: - msg.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, numOfSteps, getString(R.string.intro_bt_perm))); - btn.setOnClickListener(view -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) + mPermissionsMessage.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, getNumberOfSteps(), getString(R.string.intro_bt_perm))); + mPermissionsButton.setOnClickListener(view -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { requestPermissions(new String[] {Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT}, BLUETOOTH_REQUEST_CODE); + } }); break; case STEP_PERMISSION_BATTERY_OPTIMIZATION: - msg.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, numOfSteps, getString(R.string.intro_bat_perm))); - btn.setOnClickListener(view -> { + mPermissionsMessage.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, getNumberOfSteps(), getString(R.string.intro_bat_perm))); + mPermissionsButton.setOnClickListener(view -> { Intent intent = new Intent(); getSystemService(Context.POWER_SERVICE); intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); @@ -104,51 +117,78 @@ public class IntroActivity extends AppCompatActivity { }); break; case STEP_PERMISSION_LOCATION: - msg.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, numOfSteps, getString(R.string.intro_loc1_perm))); - btn.setOnClickListener(view -> requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE)); // Location (for BLE) + mPermissionsMessage.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, getNumberOfSteps(), getString(R.string.intro_loc1_perm))); + mPermissionsButton.setOnClickListener(view -> requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE)); // Location (for BLE) break; case STEP_PERMISSION_BACKGROUND_LOCATION: - msg.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, numOfSteps, getString(R.string.intro_loc2_perm))); - btn.setOnClickListener(view -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) requestPermissions(new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_REQUEST_CODE); + mPermissionsMessage.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, getNumberOfSteps(), getString(R.string.intro_loc2_perm))); + mPermissionsButton.setOnClickListener(view -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + requestPermissions(new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_REQUEST_CODE); + } }); break; case STEP_PERMISSION_NOTIFICATION: - msg.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, numOfSteps, getString(R.string.intro_notif_perm))); - btn.setOnClickListener(view -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) requestPermissions(new String[] {Manifest.permission.POST_NOTIFICATIONS}, NOTIFICATION_REQUEST_CODE); + mPermissionsMessage.setText(String.format(Locale.getDefault(), "%s %d/%d: %s", getString(R.string.intro_step), currentStep, getNumberOfSteps(), getString(R.string.intro_notif_perm))); + mPermissionsButton.setOnClickListener(view -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + requestPermissions(new String[] {Manifest.permission.POST_NOTIFICATIONS}, NOTIFICATION_REQUEST_CODE); + } }); } - btn.setText(String.format(Locale.getDefault(), "%s (%d/%d)", getString(R.string.intro_allow), currentStep, numOfSteps)); + mPermissionsButton.setText(String.format(Locale.getDefault(), "%s (%d/%d)", getString(R.string.intro_allow), currentStep, getNumberOfSteps())); }); } + private int getNumberOfSteps() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return 5; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + return 4; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return 3; + } + + return 2; + } + @Override - public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case BLUETOOTH_REQUEST_CODE: - if (!hasAllPermissionsGranted(grantResults)) Toast.makeText(this, getString(R.string.msg_bt_perm), Toast.LENGTH_LONG).show(); + if (!hasAllPermissionsGranted(grantResults)) { + Toast.makeText(this, getString(R.string.msg_bt_perm), Toast.LENGTH_LONG).show(); + } break; case LOCATION_REQUEST_CODE: - if (!hasAllPermissionsGranted(grantResults)) Toast.makeText(this, getString(R.string.msg_loc1_perm), Toast.LENGTH_LONG).show(); + if (!hasAllPermissionsGranted(grantResults)) { + Toast.makeText(this, getString(R.string.msg_loc1_perm), Toast.LENGTH_LONG).show(); + } break; case BACKGROUND_LOCATION_REQUEST_CODE: - if (!hasAllPermissionsGranted(grantResults)) Toast.makeText(this, getString(R.string.msg_loc2_perm), Toast.LENGTH_LONG).show(); + if (!hasAllPermissionsGranted(grantResults)) { + Toast.makeText(this, getString(R.string.msg_loc2_perm), Toast.LENGTH_LONG).show(); + } break; case NOTIFICATION_REQUEST_CODE: - if (!hasAllPermissionsGranted(grantResults)) Toast.makeText(this, getString(R.string.msg_notif_perm), Toast.LENGTH_LONG).show(); + if (!hasAllPermissionsGranted(grantResults)) { + Toast.makeText(this, getString(R.string.msg_notif_perm), Toast.LENGTH_LONG).show(); + } break; } } @SuppressWarnings("BooleanMethodIsAlwaysInverted") - public boolean hasAllPermissionsGranted (@NonNull int[] grantResults) { - for (int grantResult : grantResults) - if (grantResult == PackageManager.PERMISSION_DENIED) + public boolean hasAllPermissionsGranted(@NonNull int[] grantResults) { + for (int grantResult : grantResults) { + if (grantResult == PackageManager.PERMISSION_DENIED) { return false; + } + } return true; } - } diff --git a/app/src/main/java/com/dosse/airpods/ui/MainActivity.java b/app/src/main/java/com/dosse/airpods/ui/MainActivity.java index ee698a7..92e9d5f 100644 --- a/app/src/main/java/com/dosse/airpods/ui/MainActivity.java +++ b/app/src/main/java/com/dosse/airpods/ui/MainActivity.java @@ -19,9 +19,8 @@ import com.dosse.airpods.utils.PermissionUtils; import java.util.Objects; public class MainActivity extends AppCompatActivity { - @Override - protected void onCreate (Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); @@ -30,6 +29,7 @@ public class MainActivity extends AppCompatActivity { if (btAdapter == null || (btAdapter.isEnabled() && btAdapter.getBluetoothLeScanner() == null) || (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))) { startActivity(new Intent(MainActivity.this, NoBTActivity.class)); finish(); + return; } @@ -44,18 +44,18 @@ public class MainActivity extends AppCompatActivity { } @Override - public boolean onCreateOptionsMenu (Menu menu) { + public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override - public boolean onOptionsItemSelected (@NonNull MenuItem item) { + public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (item.getItemId() == R.id.menu_ab_settings) { startActivity(new Intent(this, SettingsActivity.class)); // Settings icon clicked return true; } + return false; } - } diff --git a/app/src/main/java/com/dosse/airpods/ui/NoBTActivity.java b/app/src/main/java/com/dosse/airpods/ui/NoBTActivity.java index 78256b2..80e51e3 100644 --- a/app/src/main/java/com/dosse/airpods/ui/NoBTActivity.java +++ b/app/src/main/java/com/dosse/airpods/ui/NoBTActivity.java @@ -6,11 +6,9 @@ import androidx.appcompat.app.AppCompatActivity; import com.dosse.airpods.R; public class NoBTActivity extends AppCompatActivity { - @Override - protected void onCreate (Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_no_bt); } - } diff --git a/app/src/main/java/com/dosse/airpods/ui/SettingsActivity.java b/app/src/main/java/com/dosse/airpods/ui/SettingsActivity.java index f92e0c7..68bfb96 100644 --- a/app/src/main/java/com/dosse/airpods/ui/SettingsActivity.java +++ b/app/src/main/java/com/dosse/airpods/ui/SettingsActivity.java @@ -11,9 +11,8 @@ import com.dosse.airpods.R; import com.dosse.airpods.receivers.StartupReceiver; public class SettingsActivity extends AppCompatActivity { - @Override - protected void onCreate (Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); getSupportFragmentManager() @@ -23,9 +22,8 @@ public class SettingsActivity extends AppCompatActivity { } public static class SettingsFragment extends PreferenceFragmentCompat { - @Override - public void onCreatePreferences (Bundle savedInstanceState, String rootKey) { + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.preference_screen, rootKey); getPreference("batterySaver").setOnPreferenceClickListener(preference -> { @@ -46,10 +44,8 @@ public class SettingsActivity extends AppCompatActivity { }); } - private Preference getPreference (String key) { + private Preference getPreference(String key) { return getPreferenceManager().findPreference(key); } - } - } diff --git a/app/src/main/java/com/dosse/airpods/utils/Logger.java b/app/src/main/java/com/dosse/airpods/utils/Logger.java index 213d6c9..97b52d0 100644 --- a/app/src/main/java/com/dosse/airpods/utils/Logger.java +++ b/app/src/main/java/com/dosse/airpods/utils/Logger.java @@ -5,17 +5,19 @@ import android.util.Log; import com.dosse.airpods.BuildConfig; public class Logger { - // Log is only displayed if this is a debug build, not release private static final boolean ENABLE_LOGGING = BuildConfig.DEBUG; public static final String TAG = "AirPods"; - public static void debug (String msg) { - if (ENABLE_LOGGING) Log.d(TAG, msg); + public static void debug(String msg) { + if (ENABLE_LOGGING) { + Log.d(TAG, msg); + } } - public static void error (Throwable t) { - if (ENABLE_LOGGING) Log.e(TAG, "ERROR", t); + public static void error(Throwable t) { + if (ENABLE_LOGGING) { + Log.e(TAG, "ERROR", t); + } } - } diff --git a/app/src/main/java/com/dosse/airpods/utils/MIUIWarning.java b/app/src/main/java/com/dosse/airpods/utils/MIUIWarning.java index aa45e4f..dc701f0 100644 --- a/app/src/main/java/com/dosse/airpods/utils/MIUIWarning.java +++ b/app/src/main/java/com/dosse/airpods/utils/MIUIWarning.java @@ -6,31 +6,47 @@ import androidx.appcompat.app.AlertDialog; import com.dosse.airpods.R; +import java.lang.reflect.Method; + public class MIUIWarning { + public static void show(Context context) { + Context appContext = context.getApplicationContext(); - public static void show (Context context) { try { - @SuppressLint("PrivateApi") Class c = Class.forName("android.os.SystemProperties"); - String miuiVersion = (String)c.getMethod("get", String.class).invoke(c, "ro.miui.ui.version.code"); - if (miuiVersion != null && !miuiVersion.isEmpty()) { - try { - context.getApplicationContext().openFileInput("miuiwarn").close(); - } catch (Throwable ignored) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.miui_warning); - builder.setMessage(R.string.miui_warning_desc); - builder.setNeutralButton(R.string.miui_warning_continue, (dialog, which) -> dialog.dismiss()); - builder.setOnDismissListener(dialog -> { - try { - context.getApplicationContext().openFileOutput("miuiwarn", Context.MODE_PRIVATE).close(); - } catch (Throwable ignored2) { - } - }); - builder.show(); - } + String miuiVersion = getMiuiVersion(); + if (miuiVersion == null || miuiVersion.isEmpty()) { + return; + } + + try { + appContext.openFileInput("miuiwarn").close(); + } catch (Throwable ignored) { + showAlertDialog(appContext); } } catch (Throwable ignored) { } } + @SuppressLint("PrivateApi") + private static String getMiuiVersion() throws ReflectiveOperationException { + Class systemPropertiesClazz = Class.forName("android.os.SystemProperties"); + Method systemPropertiesGet = systemPropertiesClazz.getMethod("get", String.class); + systemPropertiesGet.setAccessible(true); + + return (String)systemPropertiesGet.invoke(null, "ro.miui.ui.version.code"); + } + + private static void showAlertDialog(Context context) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.miui_warning); + builder.setMessage(R.string.miui_warning_desc); + builder.setNeutralButton(R.string.miui_warning_continue, (dialog, which) -> dialog.dismiss()); + builder.setOnDismissListener(dialog -> { + try { + context.openFileOutput("miuiwarn", Context.MODE_PRIVATE).close(); + } catch (Throwable ignored2) { + } + }); + builder.show(); + } } diff --git a/app/src/main/java/com/dosse/airpods/utils/PermissionUtils.java b/app/src/main/java/com/dosse/airpods/utils/PermissionUtils.java index 389db71..5a64934 100644 --- a/app/src/main/java/com/dosse/airpods/utils/PermissionUtils.java +++ b/app/src/main/java/com/dosse/airpods/utils/PermissionUtils.java @@ -7,54 +7,50 @@ import android.os.Build; import android.os.PowerManager; import androidx.annotation.RequiresApi; -import java.util.Objects; - import static androidx.core.content.ContextCompat.checkSelfPermission; public class PermissionUtils { - - public static boolean getBatteryOptimizationsPermission (Context context) { - try { - return Objects.requireNonNull(context.getSystemService(PowerManager.class)).isIgnoringBatteryOptimizations(context.getPackageName()); - } catch (Throwable ignored) { - return true; - } + public static boolean getBatteryOptimizationsPermission(Context context) { + return context.getSystemService(PowerManager.class).isIgnoringBatteryOptimizations(context.getPackageName()); } @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) - public static boolean getNotificationPermissions (Context context) { + public static boolean getNotificationPermissions(Context context) { return checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED; } @RequiresApi(api = Build.VERSION_CODES.S) - public static boolean getBluetoothPermissions (Context context) { + public static boolean getBluetoothPermissions(Context context) { return checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED && checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED; } - public static boolean getFineLocationPermission (Context context) { + public static boolean getFineLocationPermission(Context context) { return checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; } @RequiresApi(api = Build.VERSION_CODES.Q) - public static boolean getBackgroundLocationPermission (Context context) { + public static boolean getBackgroundLocationPermission(Context context) { return checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED; } - public static boolean getLocationPermissions (Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + public static boolean getLocationPermissions(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { return getFineLocationPermission(context) && getBackgroundLocationPermission(context); - else - return getFineLocationPermission(context); + } + + return getFineLocationPermission(context); } - public static boolean checkAllPermissions (Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) + public static boolean checkAllPermissions(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { return getNotificationPermissions(context) && getBatteryOptimizationsPermission(context) && getLocationPermissions(context) && getBluetoothPermissions(context); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) - return getBatteryOptimizationsPermission(context) && getLocationPermissions(context) && getBluetoothPermissions(context); - else - return getBatteryOptimizationsPermission(context) && getLocationPermissions(context); - } + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + return getBatteryOptimizationsPermission(context) && getLocationPermissions(context); + } + + return getBatteryOptimizationsPermission(context) && getLocationPermissions(context) && getBluetoothPermissions(context); + } } diff --git a/app/src/main/java/com/dosse/airpods/utils/SharedPreferencesUtils.java b/app/src/main/java/com/dosse/airpods/utils/SharedPreferencesUtils.java index 54dd5d7..55674af 100644 --- a/app/src/main/java/com/dosse/airpods/utils/SharedPreferencesUtils.java +++ b/app/src/main/java/com/dosse/airpods/utils/SharedPreferencesUtils.java @@ -5,10 +5,8 @@ import android.content.SharedPreferences; import androidx.preference.PreferenceManager; public class SharedPreferencesUtils { - - public static boolean isSavingBattery (Context context) { + public static boolean isSavingBattery(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); return prefs.getBoolean("batterySaver", false); } - }