15 Commits
33 changed files with 192 additions and 101 deletions
+1
View File
@@ -47,6 +47,7 @@
* Apple AirPods 2nd gen * Apple AirPods 2nd gen
* Apple AirPods 3rd gen * Apple AirPods 3rd gen
* Apple AirPods Pro * Apple AirPods Pro
* Apple AirPods Pro 2
* Apple AirPods Max * Apple AirPods Max
* Beats X * Beats X
* Beats Flex * Beats Flex
+13 -9
View File
@@ -1,15 +1,17 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 31 namespace 'com.dosse.airpods'
buildToolsVersion '32.0.0'
compileSdkVersion 33
buildToolsVersion '33.0.0'
defaultConfig { defaultConfig {
applicationId "com.dosse.airpods" applicationId "com.dosse.airpods"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 31 targetSdkVersion 33
versionCode 20 versionCode 22
versionName '1.8' versionName '1.9.1'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -22,17 +24,19 @@ android {
} }
} }
lintOptions {
abortOnError false
}
compileOptions { compileOptions {
sourceCompatibility = 11 sourceCompatibility = 11
targetCompatibility = 11 targetCompatibility = 11
} }
lint {
abortOnError false
}
} }
dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1' //noinspection GradleDependency 1.5.0/1.5.1 is broken
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'androidx.preference:preference:1.2.0' implementation 'androidx.preference:preference:1.2.0'
} }
+2 -2
View File
@@ -11,8 +11,8 @@
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 20, "versionCode": 21,
"versionName": "1.8", "versionName": "1.9",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],
+9 -7
View File
@@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dosse.airpods"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@@ -23,7 +27,8 @@
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme"
tools:ignore="DataExtractionRules">
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.MainActivity"
@@ -47,13 +52,10 @@
android:launchMode="singleTop" android:launchMode="singleTop"
android:parentActivityName=".ui.MainActivity" /> android:parentActivityName=".ui.MainActivity" />
<activity <activity android:name=".ui.NoBTActivity" />
android:name=".ui.NoBTActivity"
android:label="@string/app_name" />
<activity <activity
android:name=".ui.IntroActivity" android:name=".ui.IntroActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<receiver <receiver
@@ -8,9 +8,9 @@ import androidx.core.app.NotificationCompat;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.PodsStatus; import com.dosse.airpods.pods.PodsStatus;
import com.dosse.airpods.pods.data.IPods; import com.dosse.airpods.pods.models.IPods;
import com.dosse.airpods.pods.data.RegularPods; import com.dosse.airpods.pods.models.RegularPods;
import com.dosse.airpods.pods.data.SinglePods; import com.dosse.airpods.pods.models.SinglePods;
public class NotificationBuilder { public class NotificationBuilder {
public static final String TAG = "AirPods"; public static final String TAG = "AirPods";
@@ -1,4 +1,4 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods;
import android.view.View; import android.view.View;
@@ -1,5 +1,6 @@
package com.dosse.airpods.pods; package com.dosse.airpods.pods;
import android.annotation.SuppressLint;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
@@ -59,6 +60,7 @@ public class PodsService extends Service {
* *
* After decoding a beacon, the status is written to PodsStatus so that the NotificationThread can use the information * After decoding a beacon, the status is written to PodsStatus so that the NotificationThread can use the information
*/ */
@SuppressLint("MissingPermission")
private void startAirPodsScanner () { private void startAirPodsScanner () {
try { try {
Logger.debug("START SCANNER"); Logger.debug("START SCANNER");
@@ -71,7 +73,6 @@ public class PodsService extends Service {
return; return;
} }
//if (batterySaver && btScanner != null && scanCallback != null) {
if (btScanner != null && scanCallback != null) { if (btScanner != null && scanCallback != null) {
btScanner.stopScan(scanCallback); btScanner.stopScan(scanCallback);
scanCallback = null; scanCallback = null;
@@ -102,6 +103,7 @@ public class PodsService extends Service {
} }
} }
@SuppressLint("MissingPermission")
private void stopAirPodsScanner () { private void stopAirPodsScanner () {
try { try {
if (btScanner != null && scanCallback != null) { if (btScanner != null && scanCallback != null) {
@@ -233,6 +235,7 @@ public class PodsService extends Service {
} }
} }
@SuppressLint("MissingPermission")
private static boolean checkUUID (BluetoothDevice bluetoothDevice) { private static boolean checkUUID (BluetoothDevice bluetoothDevice) {
ParcelUuid[] AIRPODS_UUIDS = { ParcelUuid[] AIRPODS_UUIDS = {
ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a"), ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a"),
@@ -1,19 +1,19 @@
package com.dosse.airpods.pods; package com.dosse.airpods.pods;
import com.dosse.airpods.pods.data.AirPods1; import com.dosse.airpods.pods.models.AirPods1;
import com.dosse.airpods.pods.data.AirPods2; import com.dosse.airpods.pods.models.AirPods2;
import com.dosse.airpods.pods.data.AirPods3; import com.dosse.airpods.pods.models.AirPods3;
import com.dosse.airpods.pods.data.AirPodsMax; import com.dosse.airpods.pods.models.AirPodsMax;
import com.dosse.airpods.pods.data.AirPodsPro; import com.dosse.airpods.pods.models.AirPodsPro;
import com.dosse.airpods.pods.data.BeatsFlex; import com.dosse.airpods.pods.models.AirPodsPro2;
import com.dosse.airpods.pods.data.BeatsSolo3; import com.dosse.airpods.pods.models.BeatsFlex;
import com.dosse.airpods.pods.data.BeatsStudio3; import com.dosse.airpods.pods.models.BeatsSolo3;
import com.dosse.airpods.pods.data.BeatsX; import com.dosse.airpods.pods.models.BeatsStudio3;
import com.dosse.airpods.pods.data.IPods; import com.dosse.airpods.pods.models.BeatsX;
import com.dosse.airpods.pods.data.Pod; import com.dosse.airpods.pods.models.IPods;
import com.dosse.airpods.pods.data.Powerbeats3; import com.dosse.airpods.pods.models.Powerbeats3;
import com.dosse.airpods.pods.data.PowerbeatsPro; import com.dosse.airpods.pods.models.PowerbeatsPro;
import com.dosse.airpods.pods.data.RegularPods; import com.dosse.airpods.pods.models.RegularPods;
/** /**
* Decoding the beacon: * Decoding the beacon:
@@ -81,6 +81,8 @@ public class PodsStatus {
pods = new AirPods3(leftPod, rightPod, casePod); // Airpods 3rd gen pods = new AirPods3(leftPod, rightPod, casePod); // Airpods 3rd gen
} else if ("0E20".equals(idFull)) { } else if ("0E20".equals(idFull)) {
pods = new AirPodsPro(leftPod, rightPod, casePod); // Airpods Pro pods = new AirPodsPro(leftPod, rightPod, casePod); // Airpods Pro
} else if ("1420".equals(idFull)) {
pods = new AirPodsPro2(leftPod, rightPod, casePod); // Airpods Pro 2
} else if ('A' == idSingle) { } else if ('A' == idSingle) {
pods = new AirPodsMax(singlePod); // Airpods Max pods = new AirPodsMax(singlePod); // Airpods Max
} else if ('B' == idSingle) { } else if ('B' == idSingle) {
@@ -1,27 +0,0 @@
package com.dosse.airpods.pods.data;
public interface IPods {
String MODEL_AIRPODS_GEN1 = "airpods1";
String MODEL_AIRPODS_GEN2 = "airpods2";
String MODEL_AIRPODS_GEN3 = "airpods3";
String MODEL_AIRPODS_PRO = "airpodspro";
String MODEL_AIRPODS_MAX = "airpodsmax";
String MODEL_BEATS_X = "beatsx";
String MODEL_BEATS_FLEX = "beatsflex";
String MODEL_BEATS_SOLO_3 = "beatssolo3";
String MODEL_BEATS_STUDIO_3 = "beatsstudio3";
String MODEL_POWERBEATS_3 = "powerbeats3";
String MODEL_POWERBEATS_PRO = "powerbeatspro";
String MODEL_UNKNOWN = "unknown";
String getModel ();
boolean isSingle ();
boolean isDisconnected ();
String parseStatusForLogger ();
}
@@ -1,4 +1,6 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.pods.Pod;
public class AirPods1 extends RegularPods { public class AirPods1 extends RegularPods {
@@ -8,7 +10,7 @@ public class AirPods1 extends RegularPods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_AIRPODS_GEN1; return Constants.MODEL_AIRPODS_GEN1;
} }
} }
@@ -1,4 +1,6 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.pods.Pod;
public class AirPods2 extends RegularPods { public class AirPods2 extends RegularPods {
@@ -8,7 +10,7 @@ public class AirPods2 extends RegularPods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_AIRPODS_GEN2; return Constants.MODEL_AIRPODS_GEN2;
} }
} }
@@ -1,4 +1,6 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.pods.Pod;
public class AirPods3 extends RegularPods { public class AirPods3 extends RegularPods {
@@ -8,7 +10,7 @@ public class AirPods3 extends RegularPods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_AIRPODS_GEN3; return Constants.MODEL_AIRPODS_GEN3;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class AirPodsMax extends SinglePods { public class AirPodsMax extends SinglePods {
@@ -15,7 +16,7 @@ public class AirPodsMax extends SinglePods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_AIRPODS_MAX; return Constants.MODEL_AIRPODS_MAX;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class AirPodsPro extends RegularPods { public class AirPodsPro extends RegularPods {
@@ -25,7 +26,7 @@ public class AirPodsPro extends RegularPods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_AIRPODS_PRO; return Constants.MODEL_AIRPODS_PRO;
} }
} }
@@ -0,0 +1,32 @@
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) {
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 () {
return Constants.MODEL_AIRPODS_PRO_2;
}
}
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class BeatsFlex extends SinglePods { public class BeatsFlex extends SinglePods {
@@ -15,7 +16,7 @@ public class BeatsFlex extends SinglePods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_BEATS_FLEX; return Constants.MODEL_BEATS_FLEX;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class BeatsSolo3 extends SinglePods { public class BeatsSolo3 extends SinglePods {
@@ -15,7 +16,7 @@ public class BeatsSolo3 extends SinglePods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_BEATS_SOLO_3; return Constants.MODEL_BEATS_SOLO_3;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class BeatsStudio3 extends SinglePods { public class BeatsStudio3 extends SinglePods {
@@ -15,7 +16,7 @@ public class BeatsStudio3 extends SinglePods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_BEATS_STUDIO_3; return Constants.MODEL_BEATS_STUDIO_3;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class BeatsX extends SinglePods { public class BeatsX extends SinglePods {
@@ -15,7 +16,7 @@ public class BeatsX extends SinglePods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_BEATS_X; return Constants.MODEL_BEATS_X;
} }
} }
@@ -0,0 +1,17 @@
package com.dosse.airpods.pods.models;
public final class Constants {
static final String MODEL_AIRPODS_GEN1 = "airpods1";
static final String MODEL_AIRPODS_GEN2 = "airpods2";
static final String MODEL_AIRPODS_GEN3 = "airpods3";
static final String MODEL_AIRPODS_PRO = "airpodspro";
static final String MODEL_AIRPODS_PRO_2 = "airpodspro2";
static final String MODEL_AIRPODS_MAX = "airpodsmax";
static final String MODEL_BEATS_X = "beatsx";
static final String MODEL_BEATS_FLEX = "beatsflex";
static final String MODEL_BEATS_SOLO_3 = "beatssolo3";
static final String MODEL_BEATS_STUDIO_3 = "beatsstudio3";
static final String MODEL_POWERBEATS_3 = "powerbeats3";
static final String MODEL_POWERBEATS_PRO = "powerbeatspro";
static final String MODEL_UNKNOWN = "unknown";
}
@@ -0,0 +1,13 @@
package com.dosse.airpods.pods.models;
public interface IPods {
String getModel ();
boolean isSingle ();
boolean isDisconnected ();
String parseStatusForLogger ();
}
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class Powerbeats3 extends SinglePods { public class Powerbeats3 extends SinglePods {
@@ -15,7 +16,7 @@ public class Powerbeats3 extends SinglePods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_POWERBEATS_3; return Constants.MODEL_POWERBEATS_3;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
public class PowerbeatsPro extends RegularPods { public class PowerbeatsPro extends RegularPods {
@@ -25,7 +26,7 @@ public class PowerbeatsPro extends RegularPods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_POWERBEATS_PRO; return Constants.MODEL_POWERBEATS_PRO;
} }
} }
@@ -1,6 +1,7 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.R; import com.dosse.airpods.R;
import com.dosse.airpods.pods.Pod;
import java.util.Locale; import java.util.Locale;
@@ -48,7 +49,7 @@ public class RegularPods implements IPods {
@Override @Override
public String getModel () { public String getModel () {
return MODEL_UNKNOWN; return Constants.MODEL_UNKNOWN;
} }
@Override @Override
@@ -1,4 +1,6 @@
package com.dosse.airpods.pods.data; package com.dosse.airpods.pods.models;
import com.dosse.airpods.pods.Pod;
import java.util.Locale; import java.util.Locale;
@@ -28,8 +28,8 @@ public class IntroActivity extends AppCompatActivity {
private TextView msg; private TextView msg;
private Button btn; private Button btn;
private static final int STEP_PERMISSION_BLUETOOTH = 1, STEP_PERMISSION_BATTERY_OPTIMIZATION = 2, STEP_PERMISSION_LOCATION = 3, STEP_PERMISSION_BACKGROUND_LOCATION = 4; 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; private static final int BLUETOOTH_REQUEST_CODE = 101, LOCATION_REQUEST_CODE = 102, BACKGROUND_LOCATION_REQUEST_CODE = 103, NOTIFICATION_REQUEST_CODE = 104;
@Override @Override
protected void onCreate (Bundle savedInstanceState) { protected void onCreate (Bundle savedInstanceState) {
@@ -74,14 +74,15 @@ public class IntroActivity extends AppCompatActivity {
return STEP_PERMISSION_LOCATION; 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) if (!PermissionUtils.getBackgroundLocationPermission(this))
return STEP_PERMISSION_BACKGROUND_LOCATION; return STEP_PERMISSION_BACKGROUND_LOCATION;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) if (!PermissionUtils.getNotificationPermissions(this))
return STEP_PERMISSION_NOTIFICATION;
return 0; return 0;
} }
@SuppressLint("BatteryLife") @SuppressLint("BatteryLife")
private void initScreen () { private void initScreen () {
int currentStep = getPermissionState() - ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? 0 : 1); int currentStep = getPermissionState() - ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? 0 : 1);
int numOfSteps = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ? ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? 4 : 3) : 2; 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(() -> { runOnUiThread(() -> {
switch (getPermissionState()) { switch (getPermissionState()) {
@@ -112,6 +113,11 @@ public class IntroActivity extends AppCompatActivity {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) requestPermissions(new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_REQUEST_CODE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) requestPermissions(new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_REQUEST_CODE);
}); });
break; 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);
});
} }
btn.setText(String.format(Locale.getDefault(), "%s (%d/%d)", getString(R.string.intro_allow), currentStep, numOfSteps)); btn.setText(String.format(Locale.getDefault(), "%s (%d/%d)", getString(R.string.intro_allow), currentStep, numOfSteps));
}); });
@@ -130,6 +136,9 @@ public class IntroActivity extends AppCompatActivity {
case BACKGROUND_LOCATION_REQUEST_CODE: 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; break;
case NOTIFICATION_REQUEST_CODE:
if (!hasAllPermissionsGranted(grantResults)) Toast.makeText(this, getString(R.string.msg_notif_perm), Toast.LENGTH_LONG).show();
break;
} }
} }
@@ -21,6 +21,11 @@ public class PermissionUtils {
} }
} }
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
public static boolean getNotificationPermissions (Context context) {
return checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED;
}
@RequiresApi(api = Build.VERSION_CODES.S) @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 return checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED
@@ -44,6 +49,8 @@ public class PermissionUtils {
} }
public static boolean checkAllPermissions (Context context) { 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) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
return getBatteryOptimizationsPermission(context) && getLocationPermissions(context) && getBluetoothPermissions(context); return getBatteryOptimizationsPermission(context) && getLocationPermissions(context) && getBluetoothPermissions(context);
else else
@@ -94,6 +94,11 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/airpodsmax" /> android:text="@string/airpodsmax" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/airpodspro2" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -55,6 +55,11 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/airpodspro" /> android:text="@string/airpodspro" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/airpodspro2" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -8,7 +8,9 @@
<string name="supportedDevicesTitle"><u>מכשירים נתמכים</u></string> <string name="supportedDevicesTitle"><u>מכשירים נתמכים</u></string>
<string name="airpods1">• אפל איירפודס דור ראשון</string> <string name="airpods1">• אפל איירפודס דור ראשון</string>
<string name="airpods2">• אפל איירפודס דור שני</string> <string name="airpods2">• אפל איירפודס דור שני</string>
<string name="airpods3">• אפל איירפודס דור שלישי</string>
<string name="airpodspro">• אפל איירפודס פרו</string> <string name="airpodspro">• אפל איירפודס פרו</string>
<string name="airpodspro2">• אפל איירפודס פרו 2</string>
<string name="airpodsmax">• אפל איירפודס מקס</string> <string name="airpodsmax">• אפל איירפודס מקס</string>
<string name="beatsx">• ביטס אקס</string> <string name="beatsx">• ביטס אקס</string>
<string name="beatsflex">• ביטס פלקס</string> <string name="beatsflex">• ביטס פלקס</string>
+4 -1
View File
@@ -14,16 +14,19 @@
<string name="intro_bat_perm" tools:ignore="MissingTranslation">Battery Optimization</string> <string name="intro_bat_perm" tools:ignore="MissingTranslation">Battery Optimization</string>
<string name="intro_loc1_perm" tools:ignore="MissingTranslation">Location Permission</string> <string name="intro_loc1_perm" tools:ignore="MissingTranslation">Location Permission</string>
<string name="intro_loc2_perm" tools:ignore="MissingTranslation">Background Location Permission</string> <string name="intro_loc2_perm" tools:ignore="MissingTranslation">Background Location Permission</string>
<string name="intro_notif_perm" tools:ignore="MissingTranslation">Notification Permission</string>
<string name="msg_bt_perm" tools:ignore="MissingTranslation">Bluetooth permissions not granted, please enable them in settings.</string> <string name="msg_bt_perm" tools:ignore="MissingTranslation">Bluetooth permissions not granted, please enable them in settings.</string>
<string name="msg_loc1_perm" tools:ignore="MissingTranslation">Location permission not granted, please enable it in settings.</string> <string name="msg_loc1_perm" tools:ignore="MissingTranslation">Location permission not granted, please enable it in settings.</string>
<string name="msg_loc2_perm" tools:ignore="MissingTranslation">Background Location permission not granted, please enable it in settings.</string> <string name="msg_loc2_perm" tools:ignore="MissingTranslation">Background Location permission not granted, please enable it in settings.</string>
<string name="msg_notif_perm" tools:ignore="MissingTranslation">Notification Permission not granted, please enable it in settings.</string>
<string name="main_description">The app will show a notification when your AirPods are connected</string> <string name="main_description">The app will show a notification when your AirPods are connected</string>
<string name="supportedDevicesTitle"><u>Supported devices:</u></string> <string name="supportedDevicesTitle"><u>Supported devices:</u></string>
<string name="airpods1">&#8226; Apple AirPods 1st gen</string> <string name="airpods1">&#8226; Apple AirPods 1st gen</string>
<string name="airpods2">&#8226; Apple AirPods 2nd gen</string> <string name="airpods2">&#8226; Apple AirPods 2nd gen</string>
<string name="airpods3">&#8226; Apple AirPods 3rd gen</string> <string name="airpods3" tools:ignore="MissingTranslation">&#8226; Apple AirPods 3rd gen</string>
<string name="airpodspro">&#8226; Apple AirPods Pro</string> <string name="airpodspro">&#8226; Apple AirPods Pro</string>
<string name="airpodspro2" tools:ignore="MissingTranslation">&#8226; Apple AirPods Pro 2</string>
<string name="airpodsmax">&#8226; Apple AirPods Max</string> <string name="airpodsmax">&#8226; Apple AirPods Max</string>
<string name="beatsx">&#8226; Beats X</string> <string name="beatsx">&#8226; Beats X</string>
<string name="beatsflex">&#8226; Beats Flex</string> <string name="beatsflex">&#8226; Beats Flex</string>
+1 -5
View File
@@ -7,10 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.2.2' classpath 'com.android.tools.build:gradle:7.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
} }
} }
@@ -18,7 +15,6 @@ allprojects {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
#Wed May 18 00:26:39 IDT 2022 #Thu Sep 29 21:38:30 IDT 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME