6 Commits
11 changed files with 37 additions and 16 deletions
+2 -2
View File
@@ -6,8 +6,8 @@ android {
applicationId "com.dosse.airpods" applicationId "com.dosse.airpods"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 23 targetSdkVersion 23
versionCode 12 versionCode 13
versionName '1.2' versionName '1.3'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
@@ -37,7 +37,7 @@ import java.util.List;
/** /**
* This is the class that does most of the work. It has 3 functions: * This is the class that does most of the work. It has 3 functions:
* - Detect when AirPods are detected * - Detect when AirPods are detected
* - Receive beacons from AirPods and decode them (easier said than done thanks do google's autism) * - Receive beacons from AirPods and decode them (easier said than done thanks to google's autism)
* - Display the notification with the status * - Display the notification with the status
* *
*/ */
@@ -47,6 +47,8 @@ public class PodsService extends Service {
private static BluetoothLeScanner btScanner; private static BluetoothLeScanner btScanner;
private static int leftStatus=15, rightStatus=15, caseStatus=15; private static int leftStatus=15, rightStatus=15, caseStatus=15;
private static boolean chargeL=false, chargeR=false, chargeCase=false; private static boolean chargeL=false, chargeR=false, chargeCase=false;
private static final String MODEL_AIRPODS_NORMAL="airpods12", MODEL_AIRPODS_PRO="airpodspro";
private static String model=MODEL_AIRPODS_NORMAL;
/** /**
* The following method (startAirPodsScanner) creates a bluetoth LE scanner. * The following method (startAirPodsScanner) creates a bluetoth LE scanner.
@@ -70,6 +72,7 @@ public class PodsService extends Service {
* - The 12th and 13th characters in the string represent the charge of the left and right pods. Under unknown circumstances, they are right and left instead (see isFlipped). Values between 0 and 10 are battery 0-100%; Value 15 means it's disconnected * - The 12th and 13th characters in the string represent the charge of the left and right pods. Under unknown circumstances, they are right and left instead (see isFlipped). Values between 0 and 10 are battery 0-100%; Value 15 means it's disconnected
* - The 15th character in the string represents the charge of the case. Values between 0 and 10 are battery 0-100%; Value 15 means it's disconnected * - The 15th character in the string represents the charge of the case. Values between 0 and 10 are battery 0-100%; Value 15 means it's disconnected
* - The 14th character in the string represents the "in charge" status. Bit 0 (LSB) is the left pod; Bit 1 is the right pod; Bit 2 is the case. Bit 3 might be case open/closed but I'm not sure and it's not used * - The 14th character in the string represents the "in charge" status. Bit 0 (LSB) is the left pod; Bit 1 is the right pod; Bit 2 is the case. Bit 3 might be case open/closed but I'm not sure and it's not used
* - The 7th character in the string represents the AirPods model (E=AirPods pro)
* *
* After decoding a beacon, the status is written to leftStatus, rightStatus, caseStatus, chargeL, chargeR, chargeCase so that the NotificationThread can use the information * After decoding a beacon, the status is written to leftStatus, rightStatus, caseStatus, chargeL, chargeR, chargeCase so that the NotificationThread can use the information
* *
@@ -151,6 +154,7 @@ public class PodsService extends Service {
chargeL = (chargeStatus & 0b00000001) != 0; chargeL = (chargeStatus & 0b00000001) != 0;
chargeR = (chargeStatus & 0b00000010) != 0; chargeR = (chargeStatus & 0b00000010) != 0;
chargeCase = (chargeStatus & 0b00000100) != 0; chargeCase = (chargeStatus & 0b00000100) != 0;
if(a.charAt(7)=='E') model = MODEL_AIRPODS_PRO; else model = MODEL_AIRPODS_NORMAL; //detect if these are AirPods pro or regular ones
lastSeenConnected = System.currentTimeMillis(); lastSeenConnected = System.currentTimeMillis();
} catch (Throwable t) { } catch (Throwable t) {
if(ENABLE_LOGGING) Log.d(TAG, "" + t); if(ENABLE_LOGGING) Log.d(TAG, "" + t);
@@ -276,10 +280,22 @@ public class PodsService extends Service {
mBuilder.setCustomBigContentView(locationDisabledBig); mBuilder.setCustomBigContentView(locationDisabledBig);
} }
if(notificationShowing){ if(notificationShowing){
if(ENABLE_LOGGING) Log.d(TAG,"Left: "+leftStatus+(chargeL?"+":"")+" "+"Right: "+rightStatus+(chargeR?"+":"")+" "+"Case: "+caseStatus+(chargeCase?"+":"")); if(ENABLE_LOGGING) Log.d(TAG,"Left: "+leftStatus+(chargeL?"+":"")+" "+"Right: "+rightStatus+(chargeR?"+":"")+" "+"Case: "+caseStatus+(chargeCase?"+":"")+" "+"Model: "+model);
if(model.equals(MODEL_AIRPODS_NORMAL)){
notificationBig.setImageViewResource(R.id.leftPodImg, leftStatus <= 10 ? R.drawable.left_pod : R.drawable.left_pod_disconnected); notificationBig.setImageViewResource(R.id.leftPodImg, leftStatus <= 10 ? R.drawable.left_pod : R.drawable.left_pod_disconnected);
notificationBig.setImageViewResource(R.id.rightPodImg, rightStatus <= 10 ? R.drawable.right_pod : R.drawable.right_pod_disconnected); notificationBig.setImageViewResource(R.id.rightPodImg, rightStatus <= 10 ? R.drawable.right_pod : R.drawable.right_pod_disconnected);
notificationBig.setImageViewResource(R.id.podCaseImg, caseStatus <= 10 ? R.drawable.pod_case : R.drawable.pod_case_disconnected); notificationBig.setImageViewResource(R.id.podCaseImg, caseStatus <= 10 ? R.drawable.pod_case : R.drawable.pod_case_disconnected);
notificationSmall.setImageViewResource(R.id.leftPodImg, leftStatus <= 10 ? R.drawable.left_pod : R.drawable.left_pod_disconnected);
notificationSmall.setImageViewResource(R.id.rightPodImg, rightStatus <= 10 ? R.drawable.right_pod : R.drawable.right_pod_disconnected);
notificationSmall.setImageViewResource(R.id.podCaseImg, caseStatus <= 10 ? R.drawable.pod_case : R.drawable.pod_case_disconnected);
}else if(model.equals(MODEL_AIRPODS_PRO)){
notificationBig.setImageViewResource(R.id.leftPodImg, leftStatus <= 10 ? R.drawable.left_podpro : R.drawable.left_podpro_disconnected);
notificationBig.setImageViewResource(R.id.rightPodImg, rightStatus <= 10 ? R.drawable.right_podpro : R.drawable.right_podpro_disconnected);
notificationBig.setImageViewResource(R.id.podCaseImg, caseStatus <= 10 ? R.drawable.podpro_case : R.drawable.podpro_case_disconnected);
notificationSmall.setImageViewResource(R.id.leftPodImg, leftStatus <= 10 ? R.drawable.left_podpro : R.drawable.left_podpro_disconnected);
notificationSmall.setImageViewResource(R.id.rightPodImg, rightStatus <= 10 ? R.drawable.right_podpro : R.drawable.right_podpro_disconnected);
notificationSmall.setImageViewResource(R.id.podCaseImg, caseStatus <= 10 ? R.drawable.podpro_case : R.drawable.podpro_case_disconnected);
}
if(System.currentTimeMillis()-lastSeenConnected<TIMEOUT_CONNECTED) { if(System.currentTimeMillis()-lastSeenConnected<TIMEOUT_CONNECTED) {
notificationBig.setViewVisibility(R.id.leftPodText, View.VISIBLE); notificationBig.setViewVisibility(R.id.leftPodText, View.VISIBLE);
notificationBig.setViewVisibility(R.id.rightPodText, View.VISIBLE); notificationBig.setViewVisibility(R.id.rightPodText, View.VISIBLE);
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@@ -17,11 +17,12 @@
> >
<ImageView <ImageView
android:layout_width="30dp" android:layout_width="40dp"
android:layout_height="90dp" android:layout_height="90dp"
android:src="@drawable/left_pod" android:src="@drawable/left_pod"
android:id="@+id/leftPodImg" android:id="@+id/leftPodImg"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginBottom="6dp"
/> />
<TextView <TextView
@@ -55,10 +56,12 @@
<ImageView <ImageView
android:id="@+id/rightPodImg" android:id="@+id/rightPodImg"
android:layout_width="30dp" android:layout_width="40dp"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:src="@drawable/right_pod" /> android:src="@drawable/right_pod"
android:layout_marginBottom="6dp"
/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -91,10 +94,12 @@
<ImageView <ImageView
android:id="@+id/podCaseImg" android:id="@+id/podCaseImg"
android:layout_width="60dp" android:layout_width="80dp"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:src="@drawable/pod_case" /> android:src="@drawable/pod_case"
android:layout_marginBottom="6dp"
/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -16,7 +16,7 @@
> >
<ImageView <ImageView
android:layout_width="15dp" android:layout_width="18dp"
android:layout_height="30dp" android:layout_height="30dp"
android:src="@drawable/left_pod" android:src="@drawable/left_pod"
android:id="@+id/leftPodImg" android:id="@+id/leftPodImg"
@@ -53,7 +53,7 @@
> >
<ImageView <ImageView
android:layout_width="15dp" android:layout_width="18dp"
android:layout_height="30dp" android:layout_height="30dp"
android:src="@drawable/right_pod" android:src="@drawable/right_pod"
android:id="@+id/rightPodImg" android:id="@+id/rightPodImg"
@@ -90,7 +90,7 @@
> >
<ImageView <ImageView
android:layout_width="20dp" android:layout_width="25dp"
android:layout_height="30dp" android:layout_height="30dp"
android:src="@drawable/pod_case" android:src="@drawable/pod_case"
android:id="@+id/podCaseImg" android:id="@+id/podCaseImg"
+1 -1
View File
@@ -7,7 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.2' classpath 'com.android.tools.build:gradle:3.5.3'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files