1515import android .content .BroadcastReceiver ;
1616import android .content .Context ;
1717import android .content .Intent ;
18- import android .os .Build ;
1918import android .os .IBinder ;
2019import android .os .ParcelUuid ;
2120import android .provider .Settings ;
22- import androidx .annotation .RequiresApi ;
2321
2422import com .dosse .airpods .R ;
2523import com .dosse .airpods .notification .NotificationThread ;
4038 * - Display the notification with the status
4139 */
4240public class PodsService extends Service {
41+ private BluetoothLeScanner mBluetoothScanner ;
42+ private PodsStatus mStatus = PodsStatus .DISCONNECTED ;
4343
44- private BluetoothLeScanner btScanner ;
45- private PodsStatus status = PodsStatus . DISCONNECTED ;
44+ private static NotificationThread mNotificationThread = null ;
45+ private static boolean mMaybeConnected = false ;
4646
47- private static NotificationThread n = null ;
48- private static boolean maybeConnected = false ;
49-
50- private BroadcastReceiver btReceiver = null ;
51- private BroadcastReceiver screenReceiver = null ;
52- private PodsStatusScanCallback scanCallback = null ;
47+ private BroadcastReceiver mBluetoothReceiver = null ;
48+ private BroadcastReceiver mScreenReceiver = null ;
49+ private PodsStatusScanCallback mScanCallback = null ;
5350
5451 /**
5552 * The following method (startAirPodsScanner) creates a bluetooth LE scanner.
5653 * This scanner receives all beacons from nearby BLE devices (not just your devices!) so we need to do 3 things:
5754 * - Check that the beacon comes from something that looks like a pair of AirPods
5855 * - Make sure that it is YOUR pair of AirPods
5956 * - Decode the beacon to get the status
60- *
57+ * <p>
6158 * After decoding a beacon, the status is written to PodsStatus so that the NotificationThread can use the information
6259 */
6360 @ SuppressLint ("MissingPermission" )
64- private void startAirPodsScanner () {
61+ private void startAirPodsScanner () {
6562 try {
6663 Logger .debug ("START SCANNER" );
6764
@@ -73,111 +70,110 @@ private void startAirPodsScanner () {
7370 return ;
7471 }
7572
76- if (btScanner != null && scanCallback != null ) {
77- btScanner .stopScan (scanCallback );
78- scanCallback = null ;
73+ if (mBluetoothScanner != null && mScanCallback != null ) {
74+ mBluetoothScanner .stopScan (mScanCallback );
75+ mScanCallback = null ;
7976 }
8077
8178 if (!btAdapter .isEnabled ()) {
8279 Logger .debug ("BT Off" );
8380 return ;
8481 }
8582
86- btScanner = btAdapter .getBluetoothLeScanner ();
83+ mBluetoothScanner = btAdapter .getBluetoothLeScanner ();
8784
8885 ScanSettings scanSettings = new ScanSettings .Builder ()
8986 .setScanMode (isSavingBattery (getApplicationContext ()) ? ScanSettings .SCAN_MODE_LOW_POWER : ScanSettings .SCAN_MODE_LOW_LATENCY )
9087 .setReportDelay (1 ) // DON'T USE 0
9188 .build ();
9289
93- scanCallback = new PodsStatusScanCallback () {
90+ mScanCallback = new PodsStatusScanCallback () {
9491 @ Override
95- public void onStatus (PodsStatus newStatus ) {
96- status = newStatus ;
92+ public void onStatus (PodsStatus newStatus ) {
93+ mStatus = newStatus ;
9794 }
9895 };
9996
100- btScanner .startScan (getScanFilters (), scanSettings , scanCallback );
97+ mBluetoothScanner .startScan (getScanFilters (), scanSettings , mScanCallback );
10198 } catch (Throwable t ) {
10299 Logger .error (t );
103100 }
104101 }
105102
106103 @ SuppressLint ("MissingPermission" )
107- private void stopAirPodsScanner () {
104+ private void stopAirPodsScanner () {
108105 try {
109- if (btScanner != null && scanCallback != null ) {
106+ if (mBluetoothScanner != null && mScanCallback != null ) {
110107 Logger .debug ("STOP SCANNER" );
111108
112- btScanner .stopScan (scanCallback );
113- scanCallback = null ;
109+ mBluetoothScanner .stopScan (mScanCallback );
110+ mScanCallback = null ;
114111 }
115- status = PodsStatus .DISCONNECTED ;
112+ mStatus = PodsStatus .DISCONNECTED ;
116113 } catch (Throwable t ) {
117114 Logger .error (t );
118115 }
119116 }
120117
121- public PodsService () {
118+ public PodsService () {
122119 }
123120
124121 @ Override
125- public IBinder onBind (Intent intent ) {
122+ public IBinder onBind (Intent intent ) {
126123 return null ;
127124 }
128125
129126 /**
130127 * When the service is created, we register to get as many bluetooth and airpods related events as possible.
131128 * ACL_CONNECTED and ACL_DISCONNECTED should have been enough, but you never know with android these days.
132129 */
130+ @ SuppressLint ("UnspecifiedRegisterReceiverFlag" )
133131 @ Override
134- public void onCreate () {
132+ public void onCreate () {
135133 super .onCreate ();
136-
137- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O )
138- startForeground (101 , createBackgroundNotification ());
134+ startForeground (101 , createBackgroundNotification ());
139135
140136 unregisterBtReceiver ();
141137
142- btReceiver = new BluetoothReceiver () {
138+ mBluetoothReceiver = new BluetoothReceiver () {
143139 @ Override
144- public void onStart () {
140+ public void onStart () {
145141 // Bluetooth turned on, start/restart scanner.
146142 Logger .debug ("BT ON" );
147143 startAirPodsScanner ();
148144 }
149145
150146 @ Override
151- public void onStop () {
147+ public void onStop () {
152148 // Bluetooth turned off, stop scanner and remove notification.
153149 Logger .debug ("BT OFF" );
154- maybeConnected = false ;
150+ mMaybeConnected = false ;
155151 stopAirPodsScanner ();
156152 }
157153
158154 @ Override
159- public void onConnect (BluetoothDevice bluetoothDevice ) {
155+ public void onConnect (BluetoothDevice bluetoothDevice ) {
160156 // Airpods filter
161157 if (checkUUID (bluetoothDevice )) {
162158 // Airpods connected, show notification.
163159 Logger .debug ("ACL CONNECTED" );
164- maybeConnected = true ;
160+ mMaybeConnected = true ;
165161 }
166162 }
167163
168164 @ Override
169- public void onDisconnect (BluetoothDevice bluetoothDevice ) {
165+ public void onDisconnect (BluetoothDevice bluetoothDevice ) {
170166 // Airpods filter
171167 if (checkUUID (bluetoothDevice )) {
172168 // Airpods disconnected, remove notification but leave the scanner going.
173169 Logger .debug ("ACL DISCONNECTED" );
174- maybeConnected = false ;
170+ mMaybeConnected = false ;
175171 }
176172 }
177173 };
178174
179175 try {
180- registerReceiver (btReceiver , BluetoothReceiver .buildFilter ());
176+ registerReceiver (mBluetoothReceiver , BluetoothReceiver .buildFilter ());
181177 } catch (Throwable t ) {
182178 Logger .error (t );
183179 }
@@ -187,102 +183,108 @@ public void onDisconnect (BluetoothDevice bluetoothDevice) {
187183 BluetoothAdapter ba = ((BluetoothManager )Objects .requireNonNull (getSystemService (Context .BLUETOOTH_SERVICE ))).getAdapter ();
188184 ba .getProfileProxy (getApplicationContext (), new BluetoothListener () {
189185 @ Override
190- public boolean onConnect (BluetoothDevice device ) {
186+ public boolean onConnect (BluetoothDevice device ) {
191187 Logger .debug ("BT PROXY SERVICE CONNECTED " );
192188
193189 if (checkUUID (device )) {
194190 Logger .debug ("BT PROXY: AIRPODS ALREADY CONNECTED" );
195- maybeConnected = true ;
191+ mMaybeConnected = true ;
196192 return true ;
197193 }
198194
199195 return false ;
200196 }
201197
202198 @ Override
203- public void onDisconnect () {
199+ public void onDisconnect () {
204200 Logger .debug ("BT PROXY SERVICE DISCONNECTED " );
205- maybeConnected = false ;
201+ mMaybeConnected = false ;
206202 }
207203 }, BluetoothProfile .HEADSET );
208204
209- if (ba .isEnabled ())
210- startAirPodsScanner (); // If BT is already on when the app is started, start the scanner without waiting for an event to happen
205+ // If BT is already on when the app is started, start the scanner without waiting for an event to happen
206+ if (ba .isEnabled ()) {
207+ startAirPodsScanner ();
208+ }
211209
212210 // Screen on/off listener to suspend scanning when the screen is off, to save battery
213211 unregisterScreenReceiver ();
214212
215213 if (isSavingBattery (getApplicationContext ())) {
216- screenReceiver = new ScreenReceiver () {
214+ mScreenReceiver = new ScreenReceiver () {
217215 @ Override
218- public void onStart () {
216+ public void onStart () {
219217 Logger .debug ("SCREEN ON" );
220218 startAirPodsScanner ();
221219 }
222220
223221 @ Override
224- public void onStop () {
222+ public void onStop () {
225223 Logger .debug ("SCREEN OFF" );
226224 stopAirPodsScanner ();
227225 }
228226 };
229227
230228 try {
231- registerReceiver (screenReceiver , ScreenReceiver .buildFilter ());
229+ registerReceiver (mScreenReceiver , ScreenReceiver .buildFilter ());
232230 } catch (Throwable t ) {
233231 Logger .error (t );
234232 }
235233 }
236234 }
237235
238236 @ SuppressLint ("MissingPermission" )
239- private static boolean checkUUID (BluetoothDevice bluetoothDevice ) {
237+ private static boolean checkUUID (BluetoothDevice bluetoothDevice ) {
240238 ParcelUuid [] AIRPODS_UUIDS = {
241239 ParcelUuid .fromString ("74ec2172-0bad-4d01-8f77-997b2be0722a" ),
242240 ParcelUuid .fromString ("2a72e02b-7b99-778f-014d-ad0b7221ec74" )
243241 };
244242 ParcelUuid [] uuids = bluetoothDevice .getUuids ();
245243
246- if (uuids == null )
244+ if (uuids == null ) {
247245 return false ;
246+ }
248247
249- for (ParcelUuid u : uuids )
250- for (ParcelUuid v : AIRPODS_UUIDS )
251- if (u .equals (v )) return true ;
248+ for (ParcelUuid u : uuids ) {
249+ for (ParcelUuid v : AIRPODS_UUIDS ) {
250+ if (u .equals (v )) {
251+ return true ;
252+ }
253+ }
254+ }
252255
253256 return false ;
254257 }
255258
256259 @ Override
257- public void onDestroy () {
260+ public void onDestroy () {
258261 super .onDestroy ();
259262 unregisterBtReceiver ();
260263 unregisterScreenReceiver ();
261264 }
262265
263266 @ Override
264- public int onStartCommand (Intent intent , int flags , int startId ) {
265- if (n == null || !n .isAlive ()) {
266- n = new NotificationThread (this ) {
267+ public int onStartCommand (Intent intent , int flags , int startId ) {
268+ if (mNotificationThread == null || !mNotificationThread .isAlive ()) {
269+ mNotificationThread = new NotificationThread (this ) {
267270 @ Override
268- public boolean isConnected () {
269- return maybeConnected ;
271+ public boolean isConnected () {
272+ return mMaybeConnected ;
270273 }
271274
272275 @ Override
273- public PodsStatus getStatus () {
274- return status ;
276+ public PodsStatus getStatus () {
277+ return mStatus ;
275278 }
276279 };
277- n .start ();
280+ mNotificationThread .start ();
278281 }
279282 return START_STICKY ;
280283 }
281284
282285 // Foreground service for background notification (confusing I know).
283286 // Only enabled for API30+
284- @ RequiresApi (api = Build .VERSION_CODES .O )
285- private Notification createBackgroundNotification () {
287+ private Notification createBackgroundNotification () {
286288 final String notChannelID = "FOREGROUND_ID" ;
287289
288290 NotificationManager notManager = (NotificationManager )getSystemService (Context .NOTIFICATION_SERVICE );
@@ -307,26 +309,25 @@ private Notification createBackgroundNotification () {
307309 return builder .build ();
308310 }
309311
310- private void unregisterBtReceiver () {
312+ private void unregisterBtReceiver () {
311313 try {
312- if (btReceiver != null ) {
313- unregisterReceiver (btReceiver );
314- btReceiver = null ;
314+ if (mBluetoothReceiver != null ) {
315+ unregisterReceiver (mBluetoothReceiver );
316+ mBluetoothReceiver = null ;
315317 }
316318 } catch (Throwable t ) {
317319 Logger .error (t );
318320 }
319321 }
320322
321- private void unregisterScreenReceiver () {
323+ private void unregisterScreenReceiver () {
322324 try {
323- if (screenReceiver != null ) {
324- unregisterReceiver (screenReceiver );
325- screenReceiver = null ;
325+ if (mScreenReceiver != null ) {
326+ unregisterReceiver (mScreenReceiver );
327+ mScreenReceiver = null ;
326328 }
327329 } catch (Throwable t ) {
328330 Logger .error (t );
329331 }
330332 }
331-
332333}
0 commit comments