From 5f981665c6ca6d6e928c5e06c6eb361add85a09d Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Thu, 1 Jan 2026 20:31:25 -0500 Subject: [PATCH 01/67] Updated BTReceiver.java With relation to a known issue. https://github.com/Mystro256/autooffbluetooth/issues/7 --- .../autooffbluetooth/BTReceiver.java | 63 ++++++++++++++----- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index 24fd979..7864018 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -5,28 +5,59 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; public class BTReceiver extends BroadcastReceiver { - // "OnReceive" is an abstract function called when there's BT activity - // or state change; we can use this to try to catch a disconnection. When - // called, if no devices are connected then we can disable BT. - // See AndroidManifest.xml for the intent triggers. + // A static handler ensures the timer persists across multiple broadcast triggers + private static final Handler handler = new Handler(Looper.getMainLooper()); + + // The "Runnable" defines the task to turn off Bluetooth + private static final Runnable shutdownTask = new Runnable() { + @Override + public void run() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && adapter.isEnabled()) { + adapter.disable(); + } + } + }; + @Override public void onReceive(Context context, Intent intent) { - // Check if BT adapter is valid and hasn't already been disabled - if (BluetoothAdapter.getDefaultAdapter() != null && BluetoothAdapter.getDefaultAdapter().isEnabled()) { - int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; - for (int profileId : profiles) { - // If any device is connected, return to avoid disabling BT - if (BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(profileId) == - BluetoothProfile.STATE_CONNECTED) { - return; - } + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + + // Safety check: if BT is already off or invalid, do nothing + if (adapter == null || !adapter.isEnabled()) { + return; + } + + boolean isConnectedOrConnecting = false; + + // Check standard profiles + int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; + + for (int profileId : profiles) { + int state = adapter.getProfileConnectionState(profileId); + + // IMPROVEMENT 1: Also check if we are currently "CONNECTING" + // This prevents cutting off the radio while the car is trying to handshake + if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { + isConnectedOrConnecting = true; + break; } - // This point should only be reacted if nothing is connected - BluetoothAdapter.getDefaultAdapter().disable(); } - } + if (isConnectedOrConnecting) { + // IMPROVEMENT 2: Connection found! Cancel any pending shutdown command. + handler.removeCallbacks(shutdownTask); + } else { + // IMPROVEMENT 3: No connection found. + // Don't turn off immediately. Wait 20 seconds (20000ms). + // First, remove any existing callbacks to reset the timer (debounce) + handler.removeCallbacks(shutdownTask); + handler.postDelayed(shutdownTask, 20000); + } + } } From f40dd693272881a12e2cc8c690f12160eb3bb0d6 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Thu, 1 Jan 2026 20:33:14 -0500 Subject: [PATCH 02/67] Updated build.gradle Prepared for the next release. --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0078838..e2f739d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "com.mystro256.autooffbluetooth" minSdkVersion 15 targetSdkVersion 28 - versionCode 5 - versionName "1.4" + versionCode 6 + versionName "1.5" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { From 72fbad9973e72dd5fe9c76d8ef4f8b7daf98a114 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Thu, 1 Jan 2026 20:44:48 -0500 Subject: [PATCH 03/67] Updated AndroidManifest.xml --- app/src/main/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 164027a..7511a37 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,8 +24,9 @@ + - \ No newline at end of file + From 1b8153d0de7631f7bc5b3c307714912a7bb66717 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sat, 3 Jan 2026 14:53:24 -0500 Subject: [PATCH 04/67] Create android.yml --- .github/workflows/android.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/android.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000..7163114 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,34 @@ +name: Android CI Build APK + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + # Set up JDK + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build Debug APK + run: ./gradlew assembleDebug --no-daemon + + - name: Upload Debug APK Artifact + uses: actions/upload-artifact@v4 + with: + name: app-debug-apk-from-cloud + path: app/build/outputs/apk/debug/*.apk From e922547821c362590ac2290249948111fcef0a13 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:13:18 -0500 Subject: [PATCH 05/67] Delete app/src/test/java/com/mystro256/autooffbluetooth directory --- .../autooffbluetooth/ExampleUnitTest.java | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 app/src/test/java/com/mystro256/autooffbluetooth/ExampleUnitTest.java diff --git a/app/src/test/java/com/mystro256/autooffbluetooth/ExampleUnitTest.java b/app/src/test/java/com/mystro256/autooffbluetooth/ExampleUnitTest.java deleted file mode 100644 index 7f229e2..0000000 --- a/app/src/test/java/com/mystro256/autooffbluetooth/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.mystro256.autooffbluetooth; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file From 61097445ba02494dc927758d606c0f7814460084 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:13:28 -0500 Subject: [PATCH 06/67] Delete app/src/androidTest/java/com/mystro256/autooffbluetooth directory --- .../ExampleInstrumentedTest.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 app/src/androidTest/java/com/mystro256/autooffbluetooth/ExampleInstrumentedTest.java diff --git a/app/src/androidTest/java/com/mystro256/autooffbluetooth/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/mystro256/autooffbluetooth/ExampleInstrumentedTest.java deleted file mode 100644 index af1b326..0000000 --- a/app/src/androidTest/java/com/mystro256/autooffbluetooth/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.mystro256.autooffbluetooth; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.mystro256.autooffbluetooth", appContext.getPackageName()); - } -} From b0d83365b98ecbd7f7fef9517919428110f9d1d8 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:24:01 -0500 Subject: [PATCH 07/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index 7864018..9ff0893 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -35,14 +35,20 @@ public void onReceive(Context context, Intent intent) { boolean isConnectedOrConnecting = false; - // Check standard profiles - int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; + // Add GATT (Low Energy) profiles to the check list. + int[] profiles = { + BluetoothProfile.A2DP, + BluetoothProfile.HEADSET, + BluetoothProfile.HEALTH, + BluetoothProfile.GATT, // Added for BLE devices (Watches) + BluetoothProfile.GATT_SERVER // Added for BLE server role + }; for (int profileId : profiles) { + // Note: getProfileConnectionState is deprecated in API 31+, + // but is the correct method for this approach on older/mixed APIs. int state = adapter.getProfileConnectionState(profileId); - // IMPROVEMENT 1: Also check if we are currently "CONNECTING" - // This prevents cutting off the radio while the car is trying to handshake if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { isConnectedOrConnecting = true; break; @@ -50,11 +56,10 @@ public void onReceive(Context context, Intent intent) { } if (isConnectedOrConnecting) { - // IMPROVEMENT 2: Connection found! Cancel any pending shutdown command. + // Connection found! Cancel any pending shutdown command. handler.removeCallbacks(shutdownTask); } else { - // IMPROVEMENT 3: No connection found. - // Don't turn off immediately. Wait 20 seconds (20000ms). + // No connection found. Wait 20 seconds. // First, remove any existing callbacks to reset the timer (debounce) handler.removeCallbacks(shutdownTask); handler.postDelayed(shutdownTask, 20000); From caf6c1374a0829db130a664f95bd0f11ae60a7dc Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:34:37 -0500 Subject: [PATCH 08/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index 9ff0893..d66667e 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -1,19 +1,20 @@ package com.mystro256.autooffbluetooth; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Looper; +import java.lang.reflect.Method; +import java.util.Set; public class BTReceiver extends BroadcastReceiver { - // A static handler ensures the timer persists across multiple broadcast triggers private static final Handler handler = new Handler(Looper.getMainLooper()); - - // The "Runnable" defines the task to turn off Bluetooth + private static final Runnable shutdownTask = new Runnable() { @Override public void run() { @@ -28,41 +29,51 @@ public void run() { public void onReceive(Context context, Intent intent) { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - // Safety check: if BT is already off or invalid, do nothing if (adapter == null || !adapter.isEnabled()) { return; } - boolean isConnectedOrConnecting = false; + boolean activeConnectionFound = false; - // Add GATT (Low Energy) profiles to the check list. - int[] profiles = { - BluetoothProfile.A2DP, - BluetoothProfile.HEADSET, - BluetoothProfile.HEALTH, - BluetoothProfile.GATT, // Added for BLE devices (Watches) - BluetoothProfile.GATT_SERVER // Added for BLE server role - }; - + // Check Classic Profiles (Audio/Headset) + int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; for (int profileId : profiles) { - // Note: getProfileConnectionState is deprecated in API 31+, - // but is the correct method for this approach on older/mixed APIs. int state = adapter.getProfileConnectionState(profileId); - if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { - isConnectedOrConnecting = true; + activeConnectionFound = true; break; } } - if (isConnectedOrConnecting) { - // Connection found! Cancel any pending shutdown command. + // Iterate Paired Devices to catch BLE + if (!activeConnectionFound) { + Set pairedDevices = adapter.getBondedDevices(); + if (pairedDevices != null) { + for (BluetoothDevice device : pairedDevices) { + if (isDeviceConnected(device)) { + activeConnectionFound = true; + break; + } + } + } + } + + if (activeConnectionFound) { + // Device found! Cancel shutdown. handler.removeCallbacks(shutdownTask); } else { - // No connection found. Wait 20 seconds. - // First, remove any existing callbacks to reset the timer (debounce) + // No active device found. Schedule shutdown in 20s. handler.removeCallbacks(shutdownTask); handler.postDelayed(shutdownTask, 20000); } } + + private boolean isDeviceConnected(BluetoothDevice device) { + try { + Method m = device.getClass().getMethod("isConnected"); + return (boolean) m.invoke(device); + } catch (Exception e) { + return false; + } + } } From 574f039c0c14a335544378d32fa5b206268947a3 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:38:19 -0500 Subject: [PATCH 09/67] Update AndroidManifest.xml --- app/src/main/AndroidManifest.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7511a37..5fb72ab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,9 @@ - - + + + + + + From b42601914e0ad33087839ceb91c85e60643db29f Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:49:45 -0500 Subject: [PATCH 10/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index d66667e..b019e56 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -8,6 +8,8 @@ import android.content.Intent; import android.os.Handler; import android.os.Looper; +import android.util.Log; + import java.lang.reflect.Method; import java.util.Set; @@ -19,7 +21,8 @@ public class BTReceiver extends BroadcastReceiver { @Override public void run() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter != null && adapter.isEnabled()) { + // Final check right before turning off. + if (adapter != null && adapter.isEnabled() && !isAnyDeviceConnected(adapter)) { adapter.disable(); } } @@ -27,48 +30,52 @@ public void run() { @Override public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null || !adapter.isEnabled()) { return; } - boolean activeConnectionFound = false; + // If connected to something, CANCEL the timer immediately. + if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { + handler.removeCallbacks(shutdownTask); + return; + } - // Check Classic Profiles (Audio/Headset) + // If disconnected, or something else happened, check if ANYTHING is still alive. + if (isAnyDeviceConnected(adapter)) { + handler.removeCallbacks(shutdownTask); + } else { + // Nothing found. Start the countdown. + handler.removeCallbacks(shutdownTask); + handler.postDelayed(shutdownTask, 20000); // 20 seconds + } + } + + // Helper to check connections. + private static boolean isAnyDeviceConnected(BluetoothAdapter adapter) { + // Check Standard Profiles (Headsets, Audio). int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; for (int profileId : profiles) { - int state = adapter.getProfileConnectionState(profileId); - if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { - activeConnectionFound = true; - break; + if (adapter.getProfileConnectionState(profileId) == BluetoothProfile.STATE_CONNECTED) { + return true; } } - // Iterate Paired Devices to catch BLE - if (!activeConnectionFound) { - Set pairedDevices = adapter.getBondedDevices(); - if (pairedDevices != null) { - for (BluetoothDevice device : pairedDevices) { - if (isDeviceConnected(device)) { - activeConnectionFound = true; - break; - } + // Check Bonded Devices. This catches devices that don't report standard profiles. + Set bondedDevices = adapter.getBondedDevices(); + if (bondedDevices != null) { + for (BluetoothDevice device : bondedDevices) { + if (isConnectedReflection(device)) { + return true; } } } - - if (activeConnectionFound) { - // Device found! Cancel shutdown. - handler.removeCallbacks(shutdownTask); - } else { - // No active device found. Schedule shutdown in 20s. - handler.removeCallbacks(shutdownTask); - handler.postDelayed(shutdownTask, 20000); - } + return false; } - private boolean isDeviceConnected(BluetoothDevice device) { + private static boolean isConnectedReflection(BluetoothDevice device) { try { Method m = device.getClass().getMethod("isConnected"); return (boolean) m.invoke(device); From 67e4ce907268de5e286aa3c7c45c6aba0ec4bd77 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:53:24 -0500 Subject: [PATCH 11/67] Update AndroidManifest.xml --- app/src/main/AndroidManifest.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5fb72ab..aaae529 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,9 +2,10 @@ - + + - + + - From 00968172abe312c6d2925971a5cf1a86cf3c0b24 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:56:48 -0500 Subject: [PATCH 12/67] Update MainActivity.java --- .../autooffbluetooth/MainActivity.java | 102 ++++++++++-------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java index fb0f2c0..ff6382d 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java @@ -1,64 +1,82 @@ package com.mystro256.autooffbluetooth; +import android.Manifest; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.os.PowerManager; import android.provider.Settings; -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; -import android.widget.TextView; - -public class MainActivity extends AppCompatActivity { - - static final int DISABLE_BATTERY_OPTIMIZATION = 0; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; - protected void onActivityResult(int requestCode, int resultCode, - Intent data) { - // Call back if user agrees to disabling battery optimization - if (requestCode == DISABLE_BATTERY_OPTIMIZATION) { - if (resultCode == RESULT_OK) { - hideBatteryOptimization(); - } - } - } +import java.util.ArrayList; +import java.util.List; - // By default, a battery optimization warning amd button is shown; this - // function hides the warning/button and shows the welcome text instead - private void hideBatteryOptimization() { - TextView WelcomeText = findViewById(R.id.WelcomeText); - TextView batteryOptimizationText = findViewById(R.id.batteryOptimizationText); - Button batteryOptimizationButton = findViewById(R.id.batteryOptimizationButton); +public class MainActivity extends AppCompatActivity { - WelcomeText.setVisibility(View.VISIBLE); - batteryOptimizationText.setVisibility(View.GONE); - batteryOptimizationButton.setVisibility(View.GONE); - } + private static final int PERMISSION_REQUEST_CODE = 101; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - // Hide battery optimization warning if battery optimization is - // already disabled or user is running something older than android M - PowerManager powMan = (PowerManager) getSystemService(POWER_SERVICE); - String packageName = getPackageName(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || - powMan.isIgnoringBatteryOptimizations(packageName)) { - hideBatteryOptimization(); + // Check and request Bluetooth permissions (Required for Android 12+) + checkAndRequestPermissions(); + + // Request Battery Optimization Exemption + requestIgnoreBatteryOptimizations(); + } + + private void checkAndRequestPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + List permissionsNeeded = new ArrayList<>(); + + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT); + } + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN); + } + + if (!permissionsNeeded.isEmpty()) { + ActivityCompat.requestPermissions(this, permissionsNeeded.toArray(new String[0]), PERMISSION_REQUEST_CODE); + } } } - public void disableBatteryOptimization(View v) { - Intent intent = new Intent(); - String packageName = getPackageName(); + private void requestIgnoreBatteryOptimizations() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Intent intent = new Intent(); + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { + intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + startActivity(intent); + } + } + } - // Request disabling battery optimization and request a call back - intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - intent.setData(Uri.parse("package:" + packageName)); - startActivityForResult(intent, DISABLE_BATTERY_OPTIMIZATION); + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == PERMISSION_REQUEST_CODE) { + boolean allGranted = true; + for (int result : grantResults) { + if (result != PackageManager.PERMISSION_GRANTED) { + allGranted = false; + break; + } + } + if (!allGranted) { + Toast.makeText(this, "Bluetooth permissions are required to monitor your watch.", Toast.LENGTH_LONG).show(); + } + } } } From ef4d1fc07492594e6001bd8412efef3303b983a9 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:02:19 -0500 Subject: [PATCH 13/67] Update build.gradle --- build.gradle | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 9313af6..db9293b 100644 --- a/build.gradle +++ b/build.gradle @@ -3,22 +3,18 @@ buildscript { repositories { google() - jcenter() - + mavenCentral() // Replaced jcenter() as it is deprecated } dependencies { - classpath 'com.android.tools.build:gradle:4.1.1' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files + // Updated from 4.1.1 to 7.0.2 to support Android 12+ features + classpath 'com.android.tools.build:gradle:7.0.2' } } allprojects { repositories { google() - jcenter() - + mavenCentral() } } From d18509476f60b15a525bcadefb25051d5d7bbb32 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:07:32 -0500 Subject: [PATCH 14/67] Update build.gradle --- app/build.gradle | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e2f739d..3229030 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,28 +1,43 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + // Required to support Android 12+ Bluetooth features + compileSdkVersion 31 + defaultConfig { applicationId "com.mystro256.autooffbluetooth" - minSdkVersion 15 - targetSdkVersion 28 + minSdkVersion 21 // Increased for better modern compatibility + targetSdkVersion 31 versionCode 6 versionName "1.5" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + // Updated for AndroidX testing + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + // Required for AGP 7.0+ + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + + // MIGRATED TO ANDROIDX: Replacements for com.android.support libraries + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + + // Testing dependencies updated for AndroidX + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' } From 2fb7fa40bed0eb6c882653c93167165ed2786b90 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:14:08 -0500 Subject: [PATCH 15/67] Update build.gradle --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3229030..7d7bb74 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "com.mystro256.autooffbluetooth" - minSdkVersion 21 // Increased for better modern compatibility + minSdkVersion 15 targetSdkVersion 31 versionCode 6 versionName "1.5" From 445671d1a91430a8d5cd210afa098f3802e27662 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:15:48 -0500 Subject: [PATCH 16/67] Update gradle-wrapper.properties --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3eb1008..a7c289e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ +# Updated to version 7.0.2 to support Android 12+ features distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=23e7d37e9bb4f8dabb8a3ea7fdee9dd0428b9b1a71d298aefd65b11dccea220f -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 3f6b1fd4afc0bab054cb83836692b83ad31dd174 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:20:45 -0500 Subject: [PATCH 17/67] Update gradle-wrapper.properties --- gradle/wrapper/gradle-wrapper.properties | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a7c289e..2ec77e5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -# Updated to version 7.0.2 to support Android 12+ features distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From d09263ee876345b3736dae1307e527983d8db631 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:21:27 -0500 Subject: [PATCH 18/67] Update build.gradle --- build.gradle | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index db9293b..e970f21 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,10 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { repositories { google() - mavenCentral() // Replaced jcenter() as it is deprecated + mavenCentral() } dependencies { - // Updated from 4.1.1 to 7.0.2 to support Android 12+ features - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:7.2.2' } } From 2c9e5b3f87a84de891b62731233174f013bb31dd Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:26:48 -0500 Subject: [PATCH 19/67] Update gradle.properties --- gradle.properties | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/gradle.properties b/gradle.properties index 82618ce..e694a99 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,6 @@ # Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx1536m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - +# Mandatory fix for AndroidX dependencies +android.useAndroidX=true +android.enableJetifier=true From 84a7e83da947f6e3083ad3b6b2aef8d998421293 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:27:38 -0500 Subject: [PATCH 20/67] Update build.gradle From 40972f07488a74a7c8e2dee6169f9b10f1094c38 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:31:02 -0500 Subject: [PATCH 21/67] Delete .idea directory --- .idea/.gitignore | 3 --- .idea/codeStyles/Project.xml | 29 -------------------------- .idea/compiler.xml | 6 ------ .idea/jarRepositories.xml | 40 ------------------------------------ .idea/misc.xml | 6 ------ 5 files changed, 84 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/misc.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 30aa626..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 61a9130..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index 17fd017..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index bd152bd..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From b54b96f018c3e82895808eb8aed56044cae07bce Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:31:33 -0500 Subject: [PATCH 22/67] Update AndroidManifest.xml --- app/src/main/AndroidManifest.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index aaae529..1e5294a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,14 +16,17 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> - + - From abd6599fc4c8cb3827deb80117c3f5653960fcb3 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:39:46 -0500 Subject: [PATCH 23/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index b019e56..bcdae2a 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -1,15 +1,16 @@ package com.mystro256.autooffbluetooth; +import android.Manifest; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.os.Handler; import android.os.Looper; -import android.util.Log; - +import androidx.core.content.ContextCompat; import java.lang.reflect.Method; import java.util.Set; @@ -21,9 +22,11 @@ public class BTReceiver extends BroadcastReceiver { @Override public void run() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - // Final check right before turning off. - if (adapter != null && adapter.isEnabled() && !isAnyDeviceConnected(adapter)) { - adapter.disable(); + if (adapter != null && adapter.isEnabled()) { + try { + adapter.disable(); + } catch (SecurityException e) { + } } } }; @@ -33,45 +36,48 @@ public void onReceive(Context context, Intent intent) { String action = intent.getAction(); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter == null || !adapter.isEnabled()) { - return; + if (adapter == null || !adapter.isEnabled()) return; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) + != PackageManager.PERMISSION_GRANTED) { + return; + } } - // If connected to something, CANCEL the timer immediately. if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { handler.removeCallbacks(shutdownTask); return; } - // If disconnected, or something else happened, check if ANYTHING is still alive. - if (isAnyDeviceConnected(adapter)) { + if (isAnyDeviceConnected(context, adapter)) { handler.removeCallbacks(shutdownTask); } else { - // Nothing found. Start the countdown. handler.removeCallbacks(shutdownTask); - handler.postDelayed(shutdownTask, 20000); // 20 seconds + handler.postDelayed(shutdownTask, 20000); } } - // Helper to check connections. - private static boolean isAnyDeviceConnected(BluetoothAdapter adapter) { - // Check Standard Profiles (Headsets, Audio). + private static boolean isAnyDeviceConnected(Context context, BluetoothAdapter adapter) { + // Standard Profiles int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; for (int profileId : profiles) { - if (adapter.getProfileConnectionState(profileId) == BluetoothProfile.STATE_CONNECTED) { - return true; - } + try { + if (adapter.getProfileConnectionState(profileId) == BluetoothProfile.STATE_CONNECTED) { + return true; + } + } catch (SecurityException e) { return false; } } - // Check Bonded Devices. This catches devices that don't report standard profiles. - Set bondedDevices = adapter.getBondedDevices(); - if (bondedDevices != null) { - for (BluetoothDevice device : bondedDevices) { - if (isConnectedReflection(device)) { - return true; + // Bonded Devices + try { + Set bondedDevices = adapter.getBondedDevices(); + if (bondedDevices != null) { + for (BluetoothDevice device : bondedDevices) { + if (isConnectedReflection(device)) return true; } } - } + } catch (SecurityException e) { return false; } + return false; } From 5a93bce4fdc70c176053b59c44a8df718986fb83 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:43:22 -0500 Subject: [PATCH 24/67] Update activity_main.xml --- app/src/main/res/layout/activity_main.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9764ca0..7c5f68d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,6 @@ - - \ No newline at end of file + From 4d3b05bde6d972d2f26d0156b8c3f19f07b72e64 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:45:46 -0500 Subject: [PATCH 25/67] Update MainActivity.java --- .../com/mystro256/autooffbluetooth/MainActivity.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java index ff6382d..1791ead 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java @@ -8,6 +8,7 @@ import android.os.Bundle; import android.os.PowerManager; import android.provider.Settings; +import android.view.View; // Added for the button click import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; @@ -25,11 +26,10 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - - // Check and request Bluetooth permissions (Required for Android 12+) checkAndRequestPermissions(); + } - // Request Battery Optimization Exemption + public void disableBatteryOptimization(View view) { requestIgnoreBatteryOptimizations(); } @@ -52,13 +52,15 @@ private void checkAndRequestPermissions() { private void requestIgnoreBatteryOptimizations() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - Intent intent = new Intent(); String packageName = getPackageName(); PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { + Intent intent = new Intent(); intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); + } else { + Toast.makeText(this, "Battery optimization is already disabled.", Toast.LENGTH_SHORT).show(); } } } @@ -75,7 +77,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis } } if (!allGranted) { - Toast.makeText(this, "Bluetooth permissions are required to monitor your watch.", Toast.LENGTH_LONG).show(); + Toast.makeText(this, "Nearby Devices permission is required for watch detection.", Toast.LENGTH_LONG).show(); } } } From 3333c53f0d504c931f5264531e64217624bc1242 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 16:03:59 -0500 Subject: [PATCH 26/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index bcdae2a..675e5df 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -10,12 +10,14 @@ import android.content.pm.PackageManager; import android.os.Handler; import android.os.Looper; +import android.util.Log; import androidx.core.content.ContextCompat; import java.lang.reflect.Method; import java.util.Set; public class BTReceiver extends BroadcastReceiver { + private static final String TAG = "BTReceiver"; private static final Handler handler = new Handler(Looper.getMainLooper()); private static final Runnable shutdownTask = new Runnable() { @@ -23,9 +25,11 @@ public class BTReceiver extends BroadcastReceiver { public void run() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null && adapter.isEnabled()) { + Log.d(TAG, "Countdown finished. Turning off Bluetooth..."); try { adapter.disable(); } catch (SecurityException e) { + Log.e(TAG, "Permission denied while disabling BT"); } } } @@ -44,39 +48,64 @@ public void onReceive(Context context, Intent intent) { } } - if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { - handler.removeCallbacks(shutdownTask); - return; + // Handle Bluetooth manually turned off elsewhere + if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { + int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + if (state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_OFF) { + handler.removeCallbacks(shutdownTask); + return; + } } + Log.d(TAG, "Action received: " + action); + + // Logic check: if anything connected. if (isAnyDeviceConnected(context, adapter)) { + Log.d(TAG, "Device detected. Cancelling/Preventing shutdown."); handler.removeCallbacks(shutdownTask); } else { + Log.d(TAG, "No devices detected. Starting 20s countdown."); handler.removeCallbacks(shutdownTask); handler.postDelayed(shutdownTask, 20000); } } private static boolean isAnyDeviceConnected(Context context, BluetoothAdapter adapter) { - // Standard Profiles - int[] profiles = {BluetoothProfile.A2DP, BluetoothProfile.HEADSET, BluetoothProfile.HEALTH}; + // Check Standard Profiles (Audio, Input, Data) + int[] profiles = { + BluetoothProfile.A2DP, // Standard Audio + BluetoothProfile.HEADSET, // Voice Calls + BluetoothProfile.GATT, // Low Energy Data (Watches/App-linked headphones) + BluetoothProfile.HID_HOST // Input (Keyboards/Media buttons) + }; + for (int profileId : profiles) { try { - if (adapter.getProfileConnectionState(profileId) == BluetoothProfile.STATE_CONNECTED) { + int state = adapter.getProfileConnectionState(profileId); + // If connected OR in the middle of connecting, consider it active + if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { + Log.d(TAG, "Active connection found in profile: " + profileId); return true; } - } catch (SecurityException e) { return false; } + } catch (Exception e) { + // Profile not supported on this device, ignore + } } - // Bonded Devices + // Check Bonded Devices via Reflection try { Set bondedDevices = adapter.getBondedDevices(); if (bondedDevices != null) { for (BluetoothDevice device : bondedDevices) { - if (isConnectedReflection(device)) return true; + if (isConnectedReflection(device)) { + Log.d(TAG, "Active connection detected on: " + device.getName()); + return true; + } } } - } catch (SecurityException e) { return false; } + } catch (SecurityException e) { + Log.e(TAG, "Permission error during Bonded Device check"); + } return false; } From 7dd40d668159e80c4ead946e08506fe4e1b7ea41 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 16:11:56 -0500 Subject: [PATCH 27/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index 675e5df..6e30ec7 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -20,16 +20,18 @@ public class BTReceiver extends BroadcastReceiver { private static final String TAG = "BTReceiver"; private static final Handler handler = new Handler(Looper.getMainLooper()); + // Task that actually turns off Bluetooth private static final Runnable shutdownTask = new Runnable() { @Override public void run() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null && adapter.isEnabled()) { - Log.d(TAG, "Countdown finished. Turning off Bluetooth..."); + // Final double-check: ensure nothing connected in the last 20 seconds + Log.d(TAG, "Countdown finished. Disabling Bluetooth..."); try { adapter.disable(); } catch (SecurityException e) { - Log.e(TAG, "Permission denied while disabling BT"); + Log.e(TAG, "SecurityException: Cannot disable BT. Ensure permission is granted."); } } } @@ -41,14 +43,17 @@ public void onReceive(Context context, Intent intent) { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null || !adapter.isEnabled()) return; + + // Security Check for Android 12+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + Log.e(TAG, "Missing BLUETOOTH_CONNECT permission. Cannot run logic."); return; } } - // Handle Bluetooth manually turned off elsewhere + // Stop timer if Bluetooth is already being turned off manually if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); if (state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_OFF) { @@ -59,36 +64,37 @@ public void onReceive(Context context, Intent intent) { Log.d(TAG, "Action received: " + action); - // Logic check: if anything connected. + // Check if any device is currently active if (isAnyDeviceConnected(context, adapter)) { - Log.d(TAG, "Device detected. Cancelling/Preventing shutdown."); + Log.d(TAG, "Device(s) currently connected. Cancelling countdown."); handler.removeCallbacks(shutdownTask); } else { - Log.d(TAG, "No devices detected. Starting 20s countdown."); + Log.d(TAG, "No active connections detected. Starting 20s countdown."); handler.removeCallbacks(shutdownTask); handler.postDelayed(shutdownTask, 20000); } } private static boolean isAnyDeviceConnected(Context context, BluetoothAdapter adapter) { - // Check Standard Profiles (Audio, Input, Data) + // Check Standard Profiles int[] profiles = { - BluetoothProfile.A2DP, // Standard Audio - BluetoothProfile.HEADSET, // Voice Calls - BluetoothProfile.GATT, // Low Energy Data (Watches/App-linked headphones) - BluetoothProfile.HID_HOST // Input (Keyboards/Media buttons) + BluetoothProfile.A2DP, // 2: Standard Media Audio + BluetoothProfile.HEADSET, // 1: Phone Calls + BluetoothProfile.GATT, // 7: Data Sync (Watches/Apps) + 4, // HID_HOST: Keyboards/Headphone Buttons + 5 // PAN: Personal Area Networking }; for (int profileId : profiles) { try { int state = adapter.getProfileConnectionState(profileId); - // If connected OR in the middle of connecting, consider it active + // If connected or connecting, consider a device present if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { - Log.d(TAG, "Active connection found in profile: " + profileId); + Log.d(TAG, "Connection active on profile ID: " + profileId); return true; } } catch (Exception e) { - // Profile not supported on this device, ignore + // Profile not supported on this specific hardware } } @@ -98,13 +104,13 @@ private static boolean isAnyDeviceConnected(Context context, BluetoothAdapter ad if (bondedDevices != null) { for (BluetoothDevice device : bondedDevices) { if (isConnectedReflection(device)) { - Log.d(TAG, "Active connection detected on: " + device.getName()); + Log.d(TAG, "Device connected (Reflection): " + device.getName()); return true; } } } } catch (SecurityException e) { - Log.e(TAG, "Permission error during Bonded Device check"); + Log.e(TAG, "SecurityException checking bonded devices."); } return false; From f8b7ffb56c5fc716f21545e5df20a5ee922d2be9 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 16:31:59 -0500 Subject: [PATCH 28/67] Update BTReceiver.java --- .../autooffbluetooth/BTReceiver.java | 90 +++++++++---------- 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index 6e30ec7..f385cb3 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -20,18 +20,21 @@ public class BTReceiver extends BroadcastReceiver { private static final String TAG = "BTReceiver"; private static final Handler handler = new Handler(Looper.getMainLooper()); - // Task that actually turns off Bluetooth private static final Runnable shutdownTask = new Runnable() { @Override public void run() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null && adapter.isEnabled()) { - // Final double-check: ensure nothing connected in the last 20 seconds - Log.d(TAG, "Countdown finished. Disabling Bluetooth..."); - try { - adapter.disable(); - } catch (SecurityException e) { - Log.e(TAG, "SecurityException: Cannot disable BT. Ensure permission is granted."); + // If nothing has reconnected in 20 seconds, disable Bluetooth. + if (!isAnyDeviceConnected(adapter)) { + Log.d(TAG, "Confirmed: No devices. Turning off Bluetooth."); + try { + adapter.disable(); + } catch (SecurityException e) { + Log.e(TAG, "Permission denied for disable()"); + } + } else { + Log.d(TAG, "Device reconnected during countdown. Aborting shutdown."); } } } @@ -43,75 +46,62 @@ public void onReceive(Context context, Intent intent) { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null || !adapter.isEnabled()) return; - - // Security Check for Android 12+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) - != PackageManager.PERMISSION_GRANTED) { - Log.e(TAG, "Missing BLUETOOTH_CONNECT permission. Cannot run logic."); - return; - } - } - - // Stop timer if Bluetooth is already being turned off manually - if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); - if (state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_OFF) { - handler.removeCallbacks(shutdownTask); - return; - } + != PackageManager.PERMISSION_GRANTED) return; } - Log.d(TAG, "Action received: " + action); + Log.d(TAG, "Received Broadcast: " + action); - // Check if any device is currently active - if (isAnyDeviceConnected(context, adapter)) { - Log.d(TAG, "Device(s) currently connected. Cancelling countdown."); + // If a device connects, always stop the timer immediately. + if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { + Log.d(TAG, "ACL_CONNECTED: Stopping timer."); handler.removeCallbacks(shutdownTask); - } else { - Log.d(TAG, "No active connections detected. Starting 20s countdown."); - handler.removeCallbacks(shutdownTask); - handler.postDelayed(shutdownTask, 20000); + return; + } + + // If a device disconnects. + if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) || + BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) { + + Log.d(TAG, "ACL_DISCONNECTED: Triggering 20s countdown."); + + // We wait 2 seconds before checking "isAnyDeviceConnected" to let the stack finish the disconnection process. + handler.postDelayed(() -> { + if (!isAnyDeviceConnected(adapter)) { + handler.removeCallbacks(shutdownTask); + handler.postDelayed(shutdownTask, 20000); + } + }, 2000); } } - private static boolean isAnyDeviceConnected(Context context, BluetoothAdapter adapter) { - // Check Standard Profiles - int[] profiles = { - BluetoothProfile.A2DP, // 2: Standard Media Audio - BluetoothProfile.HEADSET, // 1: Phone Calls - BluetoothProfile.GATT, // 7: Data Sync (Watches/Apps) - 4, // HID_HOST: Keyboards/Headphone Buttons - 5 // PAN: Personal Area Networking - }; + private static boolean isAnyDeviceConnected(BluetoothAdapter adapter) { + // Standard Profiles: 1=Headset, 2=A2DP, 7=GATT, 4=HID, 5=PAN. + int[] profiles = {1, 2, 7, 4, 5}; for (int profileId : profiles) { try { int state = adapter.getProfileConnectionState(profileId); - // If connected or connecting, consider a device present - if (state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) { - Log.d(TAG, "Connection active on profile ID: " + profileId); + if (state == BluetoothProfile.STATE_CONNECTED) { + Log.d(TAG, "Active Profile Found: " + profileId); return true; } - } catch (Exception e) { - // Profile not supported on this specific hardware - } + } catch (Exception e) { } } - // Check Bonded Devices via Reflection + // Bonded Reflection. try { Set bondedDevices = adapter.getBondedDevices(); if (bondedDevices != null) { for (BluetoothDevice device : bondedDevices) { if (isConnectedReflection(device)) { - Log.d(TAG, "Device connected (Reflection): " + device.getName()); + Log.d(TAG, "Active Device Found (Reflection): " + device.getName()); return true; } } } - } catch (SecurityException e) { - Log.e(TAG, "SecurityException checking bonded devices."); - } + } catch (SecurityException e) { } return false; } From 1fdf282f1565a06a2780085f92ec48348ade42c3 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 17:08:21 -0500 Subject: [PATCH 29/67] Update MainActivity.java --- .../autooffbluetooth/MainActivity.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java index 1791ead..5ee65a4 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java @@ -8,7 +8,7 @@ import android.os.Bundle; import android.os.PowerManager; import android.provider.Settings; -import android.view.View; // Added for the button click +import android.view.View; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; @@ -54,11 +54,18 @@ private void requestIgnoreBatteryOptimizations() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String packageName = getPackageName(); PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + + // Check if already allowed if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { - Intent intent = new Intent(); - intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - intent.setData(Uri.parse("package:" + packageName)); - startActivity(intent); + try { + Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + startActivity(intent); + } catch (Exception e) { + // Fallback for devices that block direct intent + Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); + startActivity(intent); + } } else { Toast.makeText(this, "Battery optimization is already disabled.", Toast.LENGTH_SHORT).show(); } @@ -69,15 +76,10 @@ private void requestIgnoreBatteryOptimizations() { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { - boolean allGranted = true; - for (int result : grantResults) { - if (result != PackageManager.PERMISSION_GRANTED) { - allGranted = false; - break; - } - } - if (!allGranted) { - Toast.makeText(this, "Nearby Devices permission is required for watch detection.", Toast.LENGTH_LONG).show(); + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, "Bluetooth permissions granted!", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "Permissions are required to detect your watch/headphones.", Toast.LENGTH_LONG).show(); } } } From 76e0775ab1f69a794b8ff35c54c5e5704968a19b Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Sun, 4 Jan 2026 20:33:06 -0500 Subject: [PATCH 30/67] Delete fastlane/metadata/android directory --- fastlane/metadata/android/de/short_description.txt | 1 - fastlane/metadata/android/en-US/changelogs/2.txt | 1 - fastlane/metadata/android/en-US/changelogs/3.txt | 2 -- fastlane/metadata/android/en-US/changelogs/4.txt | 2 -- fastlane/metadata/android/en-US/changelogs/5.txt | 2 -- fastlane/metadata/android/en-US/full_description.txt | 5 ----- fastlane/metadata/android/en-US/short_description.txt | 1 - fastlane/metadata/android/en-US/title.txt | 1 - fastlane/metadata/android/es-ES/full_description.txt | 6 ------ fastlane/metadata/android/es-ES/short_description.txt | 1 - fastlane/metadata/android/es-ES/title.txt | 1 - fastlane/metadata/android/fr/short_description.txt | 1 - fastlane/metadata/android/fr/title.txt | 1 - fastlane/metadata/android/pt/full_description.txt | 5 ----- fastlane/metadata/android/pt/short_description.txt | 1 - fastlane/metadata/android/pt/title.txt | 1 - 16 files changed, 32 deletions(-) delete mode 100644 fastlane/metadata/android/de/short_description.txt delete mode 100644 fastlane/metadata/android/en-US/changelogs/2.txt delete mode 100644 fastlane/metadata/android/en-US/changelogs/3.txt delete mode 100644 fastlane/metadata/android/en-US/changelogs/4.txt delete mode 100644 fastlane/metadata/android/en-US/changelogs/5.txt delete mode 100644 fastlane/metadata/android/en-US/full_description.txt delete mode 100644 fastlane/metadata/android/en-US/short_description.txt delete mode 100644 fastlane/metadata/android/en-US/title.txt delete mode 100644 fastlane/metadata/android/es-ES/full_description.txt delete mode 100644 fastlane/metadata/android/es-ES/short_description.txt delete mode 100644 fastlane/metadata/android/es-ES/title.txt delete mode 100644 fastlane/metadata/android/fr/short_description.txt delete mode 100644 fastlane/metadata/android/fr/title.txt delete mode 100644 fastlane/metadata/android/pt/full_description.txt delete mode 100644 fastlane/metadata/android/pt/short_description.txt delete mode 100644 fastlane/metadata/android/pt/title.txt diff --git a/fastlane/metadata/android/de/short_description.txt b/fastlane/metadata/android/de/short_description.txt deleted file mode 100644 index cfa5809..0000000 --- a/fastlane/metadata/android/de/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Bluetooth automatisch bei Disconnect abschalten \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/2.txt b/fastlane/metadata/android/en-US/changelogs/2.txt deleted file mode 100644 index 713a46a..0000000 --- a/fastlane/metadata/android/en-US/changelogs/2.txt +++ /dev/null @@ -1 +0,0 @@ -* Changing from leanback launcher to regular launcher to fix on Android Pie diff --git a/fastlane/metadata/android/en-US/changelogs/3.txt b/fastlane/metadata/android/en-US/changelogs/3.txt deleted file mode 100644 index dcbd1b9..0000000 --- a/fastlane/metadata/android/en-US/changelogs/3.txt +++ /dev/null @@ -1,2 +0,0 @@ -* Detects and suggests disabling battery optimization if available -* Built with newer tools diff --git a/fastlane/metadata/android/en-US/changelogs/4.txt b/fastlane/metadata/android/en-US/changelogs/4.txt deleted file mode 100644 index 1f8d5b1..0000000 --- a/fastlane/metadata/android/en-US/changelogs/4.txt +++ /dev/null @@ -1,2 +0,0 @@ -* French, Spanish, and Portuguese translations -* Fix bug: don't hide battery optimization warning if user denies disabling it diff --git a/fastlane/metadata/android/en-US/changelogs/5.txt b/fastlane/metadata/android/en-US/changelogs/5.txt deleted file mode 100644 index 7cc4e51..0000000 --- a/fastlane/metadata/android/en-US/changelogs/5.txt +++ /dev/null @@ -1,2 +0,0 @@ -* Drop unnecessary wake lock permission -* Add new icon diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt deleted file mode 100644 index 0cc2bf6..0000000 --- a/fastlane/metadata/android/en-US/full_description.txt +++ /dev/null @@ -1,5 +0,0 @@ -A simple Android app to automatically turn off bluetooth if disconnected. - -No configuration, should work as-is, no guarentees and might need you to disable battery optimization for the app. For recent versions of android, it seems to need to be launched at least once for it to work. - -If BT is disconnected and reconnected quickly, the app will avoid disabling unnecessarily. diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt deleted file mode 100644 index 7a91b18..0000000 --- a/fastlane/metadata/android/en-US/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Automatically turn off bluetooth if disconnected diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt deleted file mode 100644 index e326e10..0000000 --- a/fastlane/metadata/android/en-US/title.txt +++ /dev/null @@ -1 +0,0 @@ -Auto Off Bluetooth diff --git a/fastlane/metadata/android/es-ES/full_description.txt b/fastlane/metadata/android/es-ES/full_description.txt deleted file mode 100644 index d8fe4fa..0000000 --- a/fastlane/metadata/android/es-ES/full_description.txt +++ /dev/null @@ -1,6 +0,0 @@ -Una aplicación simple de Android para apagar automáticamente la conectividad blutooth en caso que este sea desconectado. - -No se necesita configuración, deberia de funcionar tal cual. No se garantiza su funcionamiento y puede que se llegue a necesitar la desactivación de la optimización de energía para la aplicación. Para versiones recientes de android parece que se necesita inicializar el programa al menos una véz. - -Si el bluetooth se desconecta y reconecta de forma rápida, la aplicación evitará ser activada de forma innecesaria. - diff --git a/fastlane/metadata/android/es-ES/short_description.txt b/fastlane/metadata/android/es-ES/short_description.txt deleted file mode 100644 index 9ca6904..0000000 --- a/fastlane/metadata/android/es-ES/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Apagar el blutooth automáticamente en caso que sea desconectado. \ No newline at end of file diff --git a/fastlane/metadata/android/es-ES/title.txt b/fastlane/metadata/android/es-ES/title.txt deleted file mode 100644 index 1396bfc..0000000 --- a/fastlane/metadata/android/es-ES/title.txt +++ /dev/null @@ -1 +0,0 @@ -Auto apagador de Bluetooth \ No newline at end of file diff --git a/fastlane/metadata/android/fr/short_description.txt b/fastlane/metadata/android/fr/short_description.txt deleted file mode 100644 index 9efd4a5..0000000 --- a/fastlane/metadata/android/fr/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Désactiver automatiquement Bluetooth lors de la déconnexion diff --git a/fastlane/metadata/android/fr/title.txt b/fastlane/metadata/android/fr/title.txt deleted file mode 100644 index b1d46bd..0000000 --- a/fastlane/metadata/android/fr/title.txt +++ /dev/null @@ -1 +0,0 @@ -Auto-Désactivé Bluetooth diff --git a/fastlane/metadata/android/pt/full_description.txt b/fastlane/metadata/android/pt/full_description.txt deleted file mode 100644 index b07a0b7..0000000 --- a/fastlane/metadata/android/pt/full_description.txt +++ /dev/null @@ -1,5 +0,0 @@ -Um aplicativo Android simples para desactivar automaticamente o bluetooth quando desconectado. - -Sem configuração, deve funcionar como está, sem garantias e pode ser necessário desativar a otimização da bateria para o aplicativo. Para versões recentes do Android, parece que ele precisa ser iniciado pelo menos uma vez para funcionar. - -Se o BT for desconectado e reconectado rapidamente, o aplicativo evitará a desativação desnecessária. diff --git a/fastlane/metadata/android/pt/short_description.txt b/fastlane/metadata/android/pt/short_description.txt deleted file mode 100644 index 8d5ac51..0000000 --- a/fastlane/metadata/android/pt/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Desactivar automaticamente o bluetooth se desconectado diff --git a/fastlane/metadata/android/pt/title.txt b/fastlane/metadata/android/pt/title.txt deleted file mode 100644 index f619081..0000000 --- a/fastlane/metadata/android/pt/title.txt +++ /dev/null @@ -1 +0,0 @@ -Desligamento automático do bluetooth From a5a3cbc4451630e846d9b0ff1ed96bd6040eda19 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:29:56 -0500 Subject: [PATCH 31/67] Update build.gradle --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 7d7bb74..a3433b5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ android { compileSdkVersion 31 defaultConfig { - applicationId "com.mystro256.autooffbluetooth" + applicationId "com.mine.autooffbluetooth" minSdkVersion 15 targetSdkVersion 31 versionCode 6 From dc7537da0f643d47e35b60ae9c14dde4c6366bf1 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:30:40 -0500 Subject: [PATCH 32/67] Update AndroidManifest.xml --- app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1e5294a..5141865 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.mine.autooffbluetooth"> From a6886614cba1dbdc838fdd8eb454a30b7776e8f8 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:31:20 -0500 Subject: [PATCH 33/67] Update BTReceiver.java --- .../main/java/com/mystro256/autooffbluetooth/BTReceiver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java index f385cb3..ecc1ff7 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java @@ -1,4 +1,4 @@ -package com.mystro256.autooffbluetooth; +package com.mine.autooffbluetooth; import android.Manifest; import android.bluetooth.BluetoothAdapter; From e2ba9b937860fbc01b4134f4a877259170d93e8c Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:31:38 -0500 Subject: [PATCH 34/67] Update MainActivity.java --- .../main/java/com/mystro256/autooffbluetooth/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java index 5ee65a4..b433670 100644 --- a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java +++ b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java @@ -1,4 +1,4 @@ -package com.mystro256.autooffbluetooth; +package com.mine.autooffbluetooth; import android.Manifest; import android.content.Intent; From 1f4993c2c13bf00c169806c3f63c0759ede7a0ce Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:32:24 -0500 Subject: [PATCH 35/67] Create read.md --- app/src/main/java/com/mine/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/src/main/java/com/mine/read.md diff --git a/app/src/main/java/com/mine/read.md b/app/src/main/java/com/mine/read.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/src/main/java/com/mine/read.md @@ -0,0 +1 @@ + From ccaaab8f40dbe6cdebe636258dbf5aa0c56e9d5c Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:33:13 -0500 Subject: [PATCH 36/67] Create read.md --- app/src/main/java/com/mine/autooffbluetooth/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/src/main/java/com/mine/autooffbluetooth/read.md diff --git a/app/src/main/java/com/mine/autooffbluetooth/read.md b/app/src/main/java/com/mine/autooffbluetooth/read.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/src/main/java/com/mine/autooffbluetooth/read.md @@ -0,0 +1 @@ + From 9b987b5e66bd17550a86229133db676f2b636e65 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:34:00 -0500 Subject: [PATCH 37/67] Delete app/src/main/java/com/mine directory --- app/src/main/java/com/mine/autooffbluetooth/read.md | 1 - app/src/main/java/com/mine/read.md | 1 - 2 files changed, 2 deletions(-) delete mode 100644 app/src/main/java/com/mine/autooffbluetooth/read.md delete mode 100644 app/src/main/java/com/mine/read.md diff --git a/app/src/main/java/com/mine/autooffbluetooth/read.md b/app/src/main/java/com/mine/autooffbluetooth/read.md deleted file mode 100644 index 8b13789..0000000 --- a/app/src/main/java/com/mine/autooffbluetooth/read.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/src/main/java/com/mine/read.md b/app/src/main/java/com/mine/read.md deleted file mode 100644 index 8b13789..0000000 --- a/app/src/main/java/com/mine/read.md +++ /dev/null @@ -1 +0,0 @@ - From 1ed216c3f836e81c075f794f4db40f662b2d80f8 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:35:23 -0500 Subject: [PATCH 38/67] Create read.md --- app/src/main/java/com/mine/autooffbluetooth/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/src/main/java/com/mine/autooffbluetooth/read.md diff --git a/app/src/main/java/com/mine/autooffbluetooth/read.md b/app/src/main/java/com/mine/autooffbluetooth/read.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/src/main/java/com/mine/autooffbluetooth/read.md @@ -0,0 +1 @@ + From 0924f317364d386dd374fe45a2c7fe59ec2381d8 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:35:38 -0500 Subject: [PATCH 39/67] Add files via upload --- .../com/mine/autooffbluetooth/BTReceiver.java | 117 ++++++++++++++++++ .../mine/autooffbluetooth/MainActivity.java | 86 +++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 app/src/main/java/com/mine/autooffbluetooth/BTReceiver.java create mode 100644 app/src/main/java/com/mine/autooffbluetooth/MainActivity.java diff --git a/app/src/main/java/com/mine/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mine/autooffbluetooth/BTReceiver.java new file mode 100644 index 0000000..ecc1ff7 --- /dev/null +++ b/app/src/main/java/com/mine/autooffbluetooth/BTReceiver.java @@ -0,0 +1,117 @@ +package com.mine.autooffbluetooth; + +import android.Manifest; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import androidx.core.content.ContextCompat; +import java.lang.reflect.Method; +import java.util.Set; + +public class BTReceiver extends BroadcastReceiver { + + private static final String TAG = "BTReceiver"; + private static final Handler handler = new Handler(Looper.getMainLooper()); + + private static final Runnable shutdownTask = new Runnable() { + @Override + public void run() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && adapter.isEnabled()) { + // If nothing has reconnected in 20 seconds, disable Bluetooth. + if (!isAnyDeviceConnected(adapter)) { + Log.d(TAG, "Confirmed: No devices. Turning off Bluetooth."); + try { + adapter.disable(); + } catch (SecurityException e) { + Log.e(TAG, "Permission denied for disable()"); + } + } else { + Log.d(TAG, "Device reconnected during countdown. Aborting shutdown."); + } + } + } + }; + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + + if (adapter == null || !adapter.isEnabled()) return; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) + != PackageManager.PERMISSION_GRANTED) return; + } + + Log.d(TAG, "Received Broadcast: " + action); + + // If a device connects, always stop the timer immediately. + if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { + Log.d(TAG, "ACL_CONNECTED: Stopping timer."); + handler.removeCallbacks(shutdownTask); + return; + } + + // If a device disconnects. + if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) || + BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) { + + Log.d(TAG, "ACL_DISCONNECTED: Triggering 20s countdown."); + + // We wait 2 seconds before checking "isAnyDeviceConnected" to let the stack finish the disconnection process. + handler.postDelayed(() -> { + if (!isAnyDeviceConnected(adapter)) { + handler.removeCallbacks(shutdownTask); + handler.postDelayed(shutdownTask, 20000); + } + }, 2000); + } + } + + private static boolean isAnyDeviceConnected(BluetoothAdapter adapter) { + // Standard Profiles: 1=Headset, 2=A2DP, 7=GATT, 4=HID, 5=PAN. + int[] profiles = {1, 2, 7, 4, 5}; + + for (int profileId : profiles) { + try { + int state = adapter.getProfileConnectionState(profileId); + if (state == BluetoothProfile.STATE_CONNECTED) { + Log.d(TAG, "Active Profile Found: " + profileId); + return true; + } + } catch (Exception e) { } + } + + // Bonded Reflection. + try { + Set bondedDevices = adapter.getBondedDevices(); + if (bondedDevices != null) { + for (BluetoothDevice device : bondedDevices) { + if (isConnectedReflection(device)) { + Log.d(TAG, "Active Device Found (Reflection): " + device.getName()); + return true; + } + } + } + } catch (SecurityException e) { } + + return false; + } + + private static boolean isConnectedReflection(BluetoothDevice device) { + try { + Method m = device.getClass().getMethod("isConnected"); + return (boolean) m.invoke(device); + } catch (Exception e) { + return false; + } + } +} diff --git a/app/src/main/java/com/mine/autooffbluetooth/MainActivity.java b/app/src/main/java/com/mine/autooffbluetooth/MainActivity.java new file mode 100644 index 0000000..b433670 --- /dev/null +++ b/app/src/main/java/com/mine/autooffbluetooth/MainActivity.java @@ -0,0 +1,86 @@ +package com.mine.autooffbluetooth; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.PowerManager; +import android.provider.Settings; +import android.view.View; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import java.util.ArrayList; +import java.util.List; + +public class MainActivity extends AppCompatActivity { + + private static final int PERMISSION_REQUEST_CODE = 101; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + checkAndRequestPermissions(); + } + + public void disableBatteryOptimization(View view) { + requestIgnoreBatteryOptimizations(); + } + + private void checkAndRequestPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + List permissionsNeeded = new ArrayList<>(); + + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT); + } + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN); + } + + if (!permissionsNeeded.isEmpty()) { + ActivityCompat.requestPermissions(this, permissionsNeeded.toArray(new String[0]), PERMISSION_REQUEST_CODE); + } + } + } + + private void requestIgnoreBatteryOptimizations() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + + // Check if already allowed + if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { + try { + Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + startActivity(intent); + } catch (Exception e) { + // Fallback for devices that block direct intent + Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); + startActivity(intent); + } + } else { + Toast.makeText(this, "Battery optimization is already disabled.", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == PERMISSION_REQUEST_CODE) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, "Bluetooth permissions granted!", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "Permissions are required to detect your watch/headphones.", Toast.LENGTH_LONG).show(); + } + } + } +} From 47f3a33a8ddb5a9c3f2255c8a98f884df74e4b23 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:36:34 -0500 Subject: [PATCH 40/67] Update read.md --- app/src/main/java/com/mine/autooffbluetooth/read.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/mine/autooffbluetooth/read.md b/app/src/main/java/com/mine/autooffbluetooth/read.md index 8b13789..190a180 100644 --- a/app/src/main/java/com/mine/autooffbluetooth/read.md +++ b/app/src/main/java/com/mine/autooffbluetooth/read.md @@ -1 +1 @@ - +123 From 14c038575b053b6a66412eee43efd7d41bbc727e Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:36:43 -0500 Subject: [PATCH 41/67] Delete app/src/main/java/com/mine/autooffbluetooth/read.md --- app/src/main/java/com/mine/autooffbluetooth/read.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 app/src/main/java/com/mine/autooffbluetooth/read.md diff --git a/app/src/main/java/com/mine/autooffbluetooth/read.md b/app/src/main/java/com/mine/autooffbluetooth/read.md deleted file mode 100644 index 190a180..0000000 --- a/app/src/main/java/com/mine/autooffbluetooth/read.md +++ /dev/null @@ -1 +0,0 @@ -123 From 12477c635b8c34f57fb21fbca6545a0d3c3bb875 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:37:06 -0500 Subject: [PATCH 42/67] Delete app/src/main/java/com/mystro256 directory --- .../autooffbluetooth/BTReceiver.java | 117 ------------------ .../autooffbluetooth/MainActivity.java | 86 ------------- 2 files changed, 203 deletions(-) delete mode 100644 app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java delete mode 100644 app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java b/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java deleted file mode 100644 index ecc1ff7..0000000 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.mine.autooffbluetooth; - -import android.Manifest; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import androidx.core.content.ContextCompat; -import java.lang.reflect.Method; -import java.util.Set; - -public class BTReceiver extends BroadcastReceiver { - - private static final String TAG = "BTReceiver"; - private static final Handler handler = new Handler(Looper.getMainLooper()); - - private static final Runnable shutdownTask = new Runnable() { - @Override - public void run() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter != null && adapter.isEnabled()) { - // If nothing has reconnected in 20 seconds, disable Bluetooth. - if (!isAnyDeviceConnected(adapter)) { - Log.d(TAG, "Confirmed: No devices. Turning off Bluetooth."); - try { - adapter.disable(); - } catch (SecurityException e) { - Log.e(TAG, "Permission denied for disable()"); - } - } else { - Log.d(TAG, "Device reconnected during countdown. Aborting shutdown."); - } - } - } - }; - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - - if (adapter == null || !adapter.isEnabled()) return; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { - if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) - != PackageManager.PERMISSION_GRANTED) return; - } - - Log.d(TAG, "Received Broadcast: " + action); - - // If a device connects, always stop the timer immediately. - if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { - Log.d(TAG, "ACL_CONNECTED: Stopping timer."); - handler.removeCallbacks(shutdownTask); - return; - } - - // If a device disconnects. - if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) || - BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) { - - Log.d(TAG, "ACL_DISCONNECTED: Triggering 20s countdown."); - - // We wait 2 seconds before checking "isAnyDeviceConnected" to let the stack finish the disconnection process. - handler.postDelayed(() -> { - if (!isAnyDeviceConnected(adapter)) { - handler.removeCallbacks(shutdownTask); - handler.postDelayed(shutdownTask, 20000); - } - }, 2000); - } - } - - private static boolean isAnyDeviceConnected(BluetoothAdapter adapter) { - // Standard Profiles: 1=Headset, 2=A2DP, 7=GATT, 4=HID, 5=PAN. - int[] profiles = {1, 2, 7, 4, 5}; - - for (int profileId : profiles) { - try { - int state = adapter.getProfileConnectionState(profileId); - if (state == BluetoothProfile.STATE_CONNECTED) { - Log.d(TAG, "Active Profile Found: " + profileId); - return true; - } - } catch (Exception e) { } - } - - // Bonded Reflection. - try { - Set bondedDevices = adapter.getBondedDevices(); - if (bondedDevices != null) { - for (BluetoothDevice device : bondedDevices) { - if (isConnectedReflection(device)) { - Log.d(TAG, "Active Device Found (Reflection): " + device.getName()); - return true; - } - } - } - } catch (SecurityException e) { } - - return false; - } - - private static boolean isConnectedReflection(BluetoothDevice device) { - try { - Method m = device.getClass().getMethod("isConnected"); - return (boolean) m.invoke(device); - } catch (Exception e) { - return false; - } - } -} diff --git a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java b/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java deleted file mode 100644 index b433670..0000000 --- a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.mine.autooffbluetooth; - -import android.Manifest; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.PowerManager; -import android.provider.Settings; -import android.view.View; -import android.widget.Toast; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import java.util.ArrayList; -import java.util.List; - -public class MainActivity extends AppCompatActivity { - - private static final int PERMISSION_REQUEST_CODE = 101; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - checkAndRequestPermissions(); - } - - public void disableBatteryOptimization(View view) { - requestIgnoreBatteryOptimizations(); - } - - private void checkAndRequestPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - List permissionsNeeded = new ArrayList<>(); - - if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT); - } - if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { - permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN); - } - - if (!permissionsNeeded.isEmpty()) { - ActivityCompat.requestPermissions(this, permissionsNeeded.toArray(new String[0]), PERMISSION_REQUEST_CODE); - } - } - } - - private void requestIgnoreBatteryOptimizations() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - String packageName = getPackageName(); - PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); - - // Check if already allowed - if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { - try { - Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - intent.setData(Uri.parse("package:" + packageName)); - startActivity(intent); - } catch (Exception e) { - // Fallback for devices that block direct intent - Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); - startActivity(intent); - } - } else { - Toast.makeText(this, "Battery optimization is already disabled.", Toast.LENGTH_SHORT).show(); - } - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == PERMISSION_REQUEST_CODE) { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - Toast.makeText(this, "Bluetooth permissions granted!", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(this, "Permissions are required to detect your watch/headphones.", Toast.LENGTH_LONG).show(); - } - } - } -} From f31dc07f9d6211510fef6022eeb59a597dca27c2 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 17:09:12 -0500 Subject: [PATCH 43/67] Update README.md --- README.md | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ca94c59..93384d3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,34 @@ -# autooffbluetooth -A simple Android app to automatically turn off bluetooth if disconnected. +# Auto Off Bluetooth -No configuration, should work as-is, no guarentees and might need you to disable battery optimization for the app. For recent versions of android, it seems to need to be launched at least once for it to work. +Auto Off Bluetooth is a lightweight utility for Android designed to preserve battery life and increase device security. The app monitors your Bluetooth connection status and automatically turns off the Bluetooth radio after 20 seconds if no devices are connected. -If BT is disconnected and reconnected quickly, the app will avoid disabling unnecessarily. +## How it works -[Get it on F-Droid](https://f-droid.org/packages/com.mystro256.autooffbluetooth/) +The app listens for Bluetooth state changes in the stack and for Asynchronous Connection-Less disconnection events in the background. When a device disconnects, the app starts a timer. If the timer expires without a reconnection, the app automatically disables the Bluetooth adapter to save power. If a Bluetooth device reconnects, the app postpones the Auto Off task until the next disconnect. + +## Screenshots -Use at your own risk, all code is licensed GPLv3, see [LICENSE file](https://github.com/Mystro256/autooffbluetooth/blob/master/LICENSE) for details. +
+ App UI +
+ +## Permissions + +The app requires the following permissions to manage your Bluetooth hardware: + +* `BLUETOOTH`: Allows the app to see the status of connections. +* `BLUETOOTH_ADMIN`: Allows the app to toggle the Bluetooth radio on/off. +* `BLUETOOTH_CONNECT`: To interact with paired devices (required for Android 12+). + +## Installation & License + +Get it on GitHub +Get it at IzzyOnDroid + +--- + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +--- From 74818a3496a48924b62d3f732ff57cf04895af0a Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 17:16:05 -0500 Subject: [PATCH 44/67] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 93384d3..73775aa 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ The app requires the following permissions to manage your Bluetooth hardware: ## Installation & License -Get it on GitHub -Get it at IzzyOnDroid +Get it on GitHub +Get it at IzzyOnDroid --- From 7bfa3c9b0d226b1cf57407c7b27e43034aa7e41a Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 17:22:09 -0500 Subject: [PATCH 45/67] Create release.yml --- .github/workflows/release.yml | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a945fdf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,57 @@ +name: Android CI Build Release + +on: + push: + tags: + - '[0-9]+.[0-9]+*' + workflow_dispatch: + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + cache: gradle + + - name: Build Release APK + run: ./gradlew assembleRelease + + - name: Sign APK + uses: r0adkll/sign-android-release@v1 + id: sign_app + with: + releaseDirectory: app/build/outputs/apk/release + signingKeyBase64: ${{ secrets.SIGNING_KEY }} + alias: ${{ secrets.ALIAS }} + keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} + keyPassword: ${{ secrets.KEY_PASSWORD }} + env: + BUILD_TOOLS_VERSION: "34.0.0" + + - name: Rename and Strip Dots + id: rename_apk + run: | + + raw_tag=${GITHUB_REF#refs/tags/} + clean_tag="${raw_tag//./}" + signed_file="${{ steps.sign_app.outputs.signedReleaseFile }}" + new_name="auto-off-bluetooth-${clean_tag}.apk" + mv "$signed_file" "app/build/outputs/apk/release/$new_name" + echo "new_path=app/build/outputs/apk/release/$new_name" >> $GITHUB_OUTPUT + + - name: Upload Signed APK to GitHub Release + uses: softprops/action-gh-release@v1 + with: + files: ${{ steps.rename_apk.outputs.new_path }} + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 8a3cab557162310e89b245daf767daa31fd4fe44 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:28:47 -0500 Subject: [PATCH 46/67] Create full_description.txt --- metadata /en-US/full_description.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata /en-US/full_description.txt diff --git a/metadata /en-US/full_description.txt b/metadata /en-US/full_description.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata /en-US/full_description.txt @@ -0,0 +1 @@ +1 From 588ca9555f35d965520f075e08a9fd61bc20d8e8 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:29:42 -0500 Subject: [PATCH 47/67] Create short_description.txt --- metadata /en-US/short_description.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata /en-US/short_description.txt diff --git a/metadata /en-US/short_description.txt b/metadata /en-US/short_description.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata /en-US/short_description.txt @@ -0,0 +1 @@ +1 From 4853cea265563df3483780787791c48282b25109 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:30:00 -0500 Subject: [PATCH 48/67] Create title.txt --- metadata /en-US/title.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata /en-US/title.txt diff --git a/metadata /en-US/title.txt b/metadata /en-US/title.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata /en-US/title.txt @@ -0,0 +1 @@ +1 From 27ed7136100f4531aff214f69391c7759b24b912 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:31:54 -0500 Subject: [PATCH 49/67] Update full_description.txt --- metadata /en-US/full_description.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/metadata /en-US/full_description.txt b/metadata /en-US/full_description.txt index d00491f..78e3e67 100644 --- a/metadata /en-US/full_description.txt +++ b/metadata /en-US/full_description.txt @@ -1 +1,15 @@ -1 +Auto Off Bluetooth + +Auto Off Bluetooth is a lightweight utility for Android designed to preserve battery life and increase device security. The app monitors your Bluetooth connection status and automatically turns off the Bluetooth radio after 20 seconds if no devices are connected. + +How it works + +The app listens for Bluetooth state changes in the stack and for Asynchronous Connection-Less disconnection events in the background. When a device disconnects, the app starts a timer. If the timer expires without a reconnection, the app automatically disables the Bluetooth adapter to save power. If a Bluetooth device reconnects, the app postpones the Auto Off task until the next disconnect. + +Permissions + +The app requires the following permissions to manage your Bluetooth hardware: + +* BLUETOOTH: Allows the app to see the status of connections. +* BLUETOOTH_ADMIN: Allows the app to toggle the Bluetooth radio on/off. +* BLUETOOTH_CONNECT: To interact with paired devices (required for Android 12+). From 4a616164386f2f36aefc8a94869f8d583b5ce01d Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:36:21 -0500 Subject: [PATCH 50/67] Update short_description.txt --- metadata /en-US/short_description.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata /en-US/short_description.txt b/metadata /en-US/short_description.txt index d00491f..9dc90c7 100644 --- a/metadata /en-US/short_description.txt +++ b/metadata /en-US/short_description.txt @@ -1 +1 @@ -1 +The app monitors Bluetooth connection status and automatically turns it off. From d2ea4cdeef21082f515a1f5a5fb54082114a9598 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:37:07 -0500 Subject: [PATCH 51/67] Update title.txt --- metadata /en-US/title.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata /en-US/title.txt b/metadata /en-US/title.txt index d00491f..e326e10 100644 --- a/metadata /en-US/title.txt +++ b/metadata /en-US/title.txt @@ -1 +1 @@ -1 +Auto Off Bluetooth From ecb424fe5c9d905310562664a1345b6ee0b97f34 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:38:18 -0500 Subject: [PATCH 52/67] Create read.md --- metadata /en-US/images/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata /en-US/images/read.md diff --git a/metadata /en-US/images/read.md b/metadata /en-US/images/read.md new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata /en-US/images/read.md @@ -0,0 +1 @@ +1 From 39972ab46a08db57b095115487b1dab6a9022492 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:39:18 -0500 Subject: [PATCH 53/67] Add files via upload --- metadata /en-US/images/icon.png | Bin 0 -> 19791 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 metadata /en-US/images/icon.png diff --git a/metadata /en-US/images/icon.png b/metadata /en-US/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..22b9a954da98dec0581b05398698900d8117a8b1 GIT binary patch literal 19791 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 Date: Mon, 5 Jan 2026 19:39:36 -0500 Subject: [PATCH 54/67] Delete metadata /en-US/images/read.md --- metadata /en-US/images/read.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 metadata /en-US/images/read.md diff --git a/metadata /en-US/images/read.md b/metadata /en-US/images/read.md deleted file mode 100644 index d00491f..0000000 --- a/metadata /en-US/images/read.md +++ /dev/null @@ -1 +0,0 @@ -1 From 26b935aa1611ae58dd8bc4e736a3211551f650cd Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:40:15 -0500 Subject: [PATCH 55/67] Create read.md --- metadata /en-US/images/phoneScreenshots/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata /en-US/images/phoneScreenshots/read.md diff --git a/metadata /en-US/images/phoneScreenshots/read.md b/metadata /en-US/images/phoneScreenshots/read.md new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata /en-US/images/phoneScreenshots/read.md @@ -0,0 +1 @@ +1 From 5bc4531d3eddc09d77d941f8159be70352f6ec70 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:47:23 -0500 Subject: [PATCH 56/67] Create 1.txt --- metadata /en-US/changelogs/1.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata /en-US/changelogs/1.txt diff --git a/metadata /en-US/changelogs/1.txt b/metadata /en-US/changelogs/1.txt new file mode 100644 index 0000000..37b509f --- /dev/null +++ b/metadata /en-US/changelogs/1.txt @@ -0,0 +1 @@ +Initial release of the Auto Off Bluetooth application that is available in F-Droid repository, but seems being abandoned by its author. The app is built from the source code based on the 1.4 codebase with improved algorithm logic and Android newer versions compatibility. From 16964a460b5ef8c15b1b68f8e124b9fbdd2eb63e Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:51:03 -0500 Subject: [PATCH 57/67] Delete metadata directory --- metadata /en-US/changelogs/1.txt | 1 - metadata /en-US/full_description.txt | 15 --------------- metadata /en-US/images/icon.png | Bin 19791 -> 0 bytes .../en-US/images/phoneScreenshots/read.md | 1 - metadata /en-US/short_description.txt | 1 - metadata /en-US/title.txt | 1 - 6 files changed, 19 deletions(-) delete mode 100644 metadata /en-US/changelogs/1.txt delete mode 100644 metadata /en-US/full_description.txt delete mode 100644 metadata /en-US/images/icon.png delete mode 100644 metadata /en-US/images/phoneScreenshots/read.md delete mode 100644 metadata /en-US/short_description.txt delete mode 100644 metadata /en-US/title.txt diff --git a/metadata /en-US/changelogs/1.txt b/metadata /en-US/changelogs/1.txt deleted file mode 100644 index 37b509f..0000000 --- a/metadata /en-US/changelogs/1.txt +++ /dev/null @@ -1 +0,0 @@ -Initial release of the Auto Off Bluetooth application that is available in F-Droid repository, but seems being abandoned by its author. The app is built from the source code based on the 1.4 codebase with improved algorithm logic and Android newer versions compatibility. diff --git a/metadata /en-US/full_description.txt b/metadata /en-US/full_description.txt deleted file mode 100644 index 78e3e67..0000000 --- a/metadata /en-US/full_description.txt +++ /dev/null @@ -1,15 +0,0 @@ -Auto Off Bluetooth - -Auto Off Bluetooth is a lightweight utility for Android designed to preserve battery life and increase device security. The app monitors your Bluetooth connection status and automatically turns off the Bluetooth radio after 20 seconds if no devices are connected. - -How it works - -The app listens for Bluetooth state changes in the stack and for Asynchronous Connection-Less disconnection events in the background. When a device disconnects, the app starts a timer. If the timer expires without a reconnection, the app automatically disables the Bluetooth adapter to save power. If a Bluetooth device reconnects, the app postpones the Auto Off task until the next disconnect. - -Permissions - -The app requires the following permissions to manage your Bluetooth hardware: - -* BLUETOOTH: Allows the app to see the status of connections. -* BLUETOOTH_ADMIN: Allows the app to toggle the Bluetooth radio on/off. -* BLUETOOTH_CONNECT: To interact with paired devices (required for Android 12+). diff --git a/metadata /en-US/images/icon.png b/metadata /en-US/images/icon.png deleted file mode 100644 index 22b9a954da98dec0581b05398698900d8117a8b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19791 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 Date: Mon, 5 Jan 2026 19:53:10 -0500 Subject: [PATCH 58/67] Create 1.txt --- metadata/en-US/changelogs/1.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata/en-US/changelogs/1.txt diff --git a/metadata/en-US/changelogs/1.txt b/metadata/en-US/changelogs/1.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata/en-US/changelogs/1.txt @@ -0,0 +1 @@ +1 From c1e6d708db5f1774168f358bc5d2c72f25ce550b Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:53:33 -0500 Subject: [PATCH 59/67] Add files via upload --- metadata/en-US/changelogs/1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata/en-US/changelogs/1.txt b/metadata/en-US/changelogs/1.txt index d00491f..37b509f 100644 --- a/metadata/en-US/changelogs/1.txt +++ b/metadata/en-US/changelogs/1.txt @@ -1 +1 @@ -1 +Initial release of the Auto Off Bluetooth application that is available in F-Droid repository, but seems being abandoned by its author. The app is built from the source code based on the 1.4 codebase with improved algorithm logic and Android newer versions compatibility. From c1a7c06d408d4289284e6540276432f70dc9f843 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:54:43 -0500 Subject: [PATCH 60/67] Create read.md --- metadata/en-US/images/phoneScreenshots/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 metadata/en-US/images/phoneScreenshots/read.md diff --git a/metadata/en-US/images/phoneScreenshots/read.md b/metadata/en-US/images/phoneScreenshots/read.md new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/metadata/en-US/images/phoneScreenshots/read.md @@ -0,0 +1 @@ +1 From 5663f4271bb42cd31bc5ca604632d32fb3dcf39f Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:55:01 -0500 Subject: [PATCH 61/67] Add files via upload --- metadata/en-US/images/icon.png | Bin 0 -> 19791 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 metadata/en-US/images/icon.png diff --git a/metadata/en-US/images/icon.png b/metadata/en-US/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..22b9a954da98dec0581b05398698900d8117a8b1 GIT binary patch literal 19791 zcmb@uXIN8P*DkygA_PSspcH8_p$Sq1m2RTa6eZXIMT!lSE=4+t6#?l@r396tA|NVV zNZ1yd0%8HBiV3|)qy<89=ED8F&-a~w=eph>0){o`9CMU=)J3$7wZ+EuTh>DmwDEwY z=}`zmf*+9(njd_d3;wbUL5C#{nC?9u{9~%l&DXIjBeZ6kwIezdn4|GIa6Xsa(})wnyXI4D1F(*-o303}o}2!8|rAW`@W z5&i-p;4l9hAO5dx^nVdYgbDoLBlEwz|M#c=_uYwu)iX&t?8>g3v?J=0?{8f7kI9o9 zu!AN3VVF#td-ZIYvERVnPF&oU%t{iv@36ftMwiV+f-_yzc=f*xz6VV{e>-j%Hv90| z(h{GvA?=r~RXUvN|d+nYd9|o2yQ5#7tE!Z%^e7D%2Oyf*#$3YYbqU558JCQl$ zAR1?W#`WLhl%P3xW3p3Dgd3H^h&J#$cVPEG7<`XwqR=OF@bFXwtI~9h{|$naizv>| zDLuwaPL>r4RwB_<=(aiiv(MB#&PD$3$u=-Kq!7&SmjnNvpbSpH0yBUhv=b!y_mVrI zl6Xqy!RR#`L1G}UAOX&4D(c_g;-QD)eAI}Mk4+QMU&>ujL`9@#lmATpHo^t#|By4f z?V8r>N?M?&wwu5jIk#bQtjM9Ud^gt4I|`ZN2h$b@eyW~XyV53bCHtj@TGpd=y7{CX ze<{WSUcHpmYD!MvDiVU9?F*H3V^t&I+ueY-i%B3PuE=Ys{Jp_JXf$wo$n4~NvxUz2 z$R~3{FZr-*(h-fLlv7tvPTzC*Fd_hpzy@slCquI(osZg_8}gThR|P4fDHII>!oRx# z`Xu?imHuvR`(Nh#FsFC0^TP|)6haBYVSJBVkzKy_R}(A|gEPXvaV{$j?H8IjVq+)X zKF7kh18fX+tO_`=JCYmSyJ#sb&WC_`eh@MpK|NcYJI8J~r<*78AN{~C8@hZ|QD{k+ z-?TSgjQ`(D$Vt57{90s|MjBapugUB-VR6q<<%rgT**YwA=Qbr@Vf6rap?OVDs0P4r zX7?#n@0tJR)cpOGIe*)>p|E|B6b2DX2q#58#fTovNcAyQ7HzQ3vCFUU#(=i>F)RY{3<&6=-u}tB1DL|o#{-T?qz09|6D#L z=;Nq$eI!j3fg-Z-ga51x327H*hn(C4--oz;DYj9aA>u>Z8aL8TW)_51S>s)@h3+{Y zM2SNDru2}I%ZpdoQLJm<(3Z>*U<;J#-}^~i60OeeejTmEutqopBl_co^{qB7JQ5Az zaf3GyeDIix9sNSrKUb3#HQ zN4{y{b1ATt25Uxdf1M%h-Y+rPqm*&#lwrhY6H7qLEi<~m6N>Xs0%dk>+pdSC%jvvs zUYXvND+joC=JZoI3be-f=j*Zy3N~=%zt=u;V2vDr5H5Zwj(8~_(CdrNTv$(sXZrf_ zY-c&db|FRRP&DKywbZ_OD{L>63Ks8y3a`b{;Vh0a=v7Ay_iA~Zn z9~QGA?X5_s?=O#W%bpRvaj@z#6b7ss`6s?3WU;2uT`@#yU6~cPekaMhMb-j_i6%l$ zhCKH83$N=!cjbot*YwD2Wud7(#-C|UK`TEly?1xm9^D5sZg413fm}2oL@p=mFcj+IcYU#9#~<$WaYax!AY4pQ z+sPhO&fzl^y@`8n!SXnr`CC$Y#>ivwTV4wxH2b1wVoY`>^IMGZ9t9+Jtcx8hdEu+k z3bT|2U}5>97P6DgMqr`I!k~$UJ^n&TAL7N4TGgYO0$>HksVM-F^qMTnPNxY4)A_D?i#Q>lJqm z^na;k(^Gm8^`WmWt~~?Nc0Ek*Z{L%qz$`GoA^`LX4QXF3O*@>z`FO(b*@Lzxncn5* z^c=4bf>`K7x7?r^UB)?Fjd1sU7LXnN?o~okA#}lL_p-pW{$|9-!`$asWqvV8`E*V3 zl|~hX<^=!GIB`B{86iNNC<35_<=DbTzgPXm=#J>ChP&^+Qpa4vr=W-4>!=!ktp zh_V%<9T52>H5lXjwhZ0zl5Y;$YK>8Z?gYb!FE0+HP;cn3k*SKDj>tP6Q(3%-%l-Bw zvm^)i*g|lTx_RiOG9+}H(uCMYw%h6G{Xt57+f7rzJ{KZtl!%qY58CgqOZ6U5<#UZ< zKNAG0=RrDxu>j+4>PT2SIVfxRSQv~l@AGDN^CBl@h*O0!u6EwNP(Uo3pRAK%sl+VzU zy+biuxzbAefSy$ZIG}y`Os<0iYJT4QVyhttY3`t(4+>J+zVeulUgq)M{)|LT`fDSd z!p>!I1~&ivhQ8ag0fEwITt8^aaq_xxd`PM&+(e&#BZ75=qm%& z5{T02J|&)E3an;AG7=1uP=KfB@4YyB4Rlcku_6*aeH!)pMNlD!koL~ce*uMq33Bs% zo+FpLGTs+UDL18n^%oT>@ae!7GeInp0zrILbuWmnGyUTVbrU}%8hnXS>%MP+TJ+v?PRWO}cCi0Mp92eq^cI_V zkGG$-h7S=Q$hoKTXTdW?_v2yfz5x82Yu{EpKBUz5fhN~?>K1#R#X4fQU8kX#puVS^HJD!W6;(fK4NtUV^ya&mcmy^G62fe zAG)8Lj{_dy(3*z)E`M=}wN#&dG^nkZ&mjQ$Fb5}<`sjuu8e$e;cvBYiq;XwuGkSjP zi=in!Cbe~g0||5J7nctODN^?+on)=7hH=mrFOL=!y-D~N?NJmZMDCpQ0#)ZjEJZx9 z+TGQxy+M9$X*OOVs7%s zR1taVR8|b->0*C6O{+OYX3cu?(7`PY=#FXuL*5_&eI)%Md?w)Z%9oN%i{}EZ<$TF3yP?F;GAKF0a2*Udy~a5gHy+*fQp9< z`mn)2p3& zySZ!*)sCkc7B8za9maV-LT#a$oRahrb3I?Zw$2i3$&xeC%J#*KZI&_p!RV3NP)3P--9%@;KQh2Ru~?ih>}Dr3r*kZMu|^t`2%k;W{*XWsNszldJ~DgM zDwY;MRQM_S>Ya`JNa&DDNAFodpLra;?C18Hp1qCyJ)u`9=JcQzKgGrQcLx$Ert2u3 zBn5REgfo3`tITi?$4aRQZ$>QnzXC!7IoIP6X25r2`MfJ8p~ByAYp} zx^K+8^9AE5=lLlUnCHuVl??K62@DVy zL_!WljQzX&)E!EIv>~3fUR(;%EDUwwU6@8bEdbGRdZbL%ZR^%F-v$L+>c6{R^gxYH zP&%Go@H0jj=^aADYu@#MHAc0mFuWf+C1tO+ZrL#R8wejX5|#ru-g7=Xa-ZURKGr38 zo>gT*uh*K>&SeOIT$&|8+x|6fBLL)cGEW)xSx=H5zPYyMdQo$itM>@{df9he{o&60 zogL;CAqFCg+|IG1z?($tNA6C79`D3K0dDlUn_A8H_$!gbC=;eu$O-=Z__Wj`i{h|i zUV3w_S4QTUhwM)8xxlD6%pg_H#`y5Tr?ySa`q>jME$UDjk0F_pw3tvezkcwdS6pg+ zz3HujgbXJUUSXc<+U1X;M#n=O&1QZe_9db1Jpxg^CsH*oc-XZ((GTCPtbq(T%ncns z_q`=wN8hVAgQWsvoA{@Qxf*JJK0x#kF<%SSV`|@uW7sQ~#VZg6^_*w^D(l97#7P&W zH|KuY;haWTv-sQAUp_a78lGu?2coXq73M_RwSaq-mx{ma+--<~_zLf&?-XE`dhAxS z)yk-?D=pp6wvb+>Jd1$yZews((7NbeKslg}IHxz60m_^`(l zESfChwJ^{ip`mn^?7h0MA^`W*n-TNn+!6r?5z!cP`b>~#lCH^ZiYY%mJLQ&Dg$l3T zI>&e1?EwA|k43xiq12>-XR*j2Oww?7V$2~6K|WyD9hCw1KlHpj?B1ReIR3uaK|ZkS zda;F|1%B{Jw!>>0u~rfhy`EyEER=F-gL7&-DLY`?&9dw42Zzdo%ki&iBP^OBa^IRN zKoK!78M6^a`NN+6A_ImpyC3I2Xd8fy^tu!x8cpeWPhgOiR)$^~vASknlr#i~|2j3M z%b}fB;k9CX|B87tV#C6epC&S(_0e=_$IXNa3!zBLx?=>9q2=ZoFClRLm`)ka!LlD2qlW57mU)<#CpYD=h zQ8~o*!eb+Z))Z0_VeK`-^8Q^ju~%}>4_QR}WWREGc6T)<0jg?9v7Kd^T{d~AEp4|? zex+3k?oivp zv-(~h!L9kK^@Nq6lMDlnP^Nfp!bitUsmG;ybGxEGVmeB(hvj=}8dCg@o#rDl3FJO^ zQo8r5(C7_<983Ij1h+4ZrgKdN28gTTe1V8;D>s2x`l5)?{)X%ahwjlr9Baw<8gbB% z7TUW97an}N9&uLZrx~m`9~?|X8&iXY9Ci) zx`_~)=X1V-b_T`*AEXq!Da7?E;kZTAgeYRTqbHUUcCcUt)3FdpBq4JXR0xvHQU}Ra zJI%C6@mu$REdl({#>f>F{R#~HP~w4c`STCGANb-^IVvw#(HAF=K#w_rC&J^-C9EcV zJHApYwM^P_rk>MdPUHv4BqViB{`n(;DcQ?jM%~|E!j?0F0yVRlwx*1eGDV!|t9^o$ zdVD0abfMJC&toLYdi(a1W%m4sq`$7>Bg8d$s*fD-lr!L_6v6-T>L8fvn|GObOW)&! z>a{z9)zy2JG(SV@%7>~heBsln9S~xnCf%Vix#o1Qbz_|*-gsR+#|K0hyjEV` zxzYgPY=bH4No{?vthpDCT<2&A&Q0NTbL$@~rB`P7-1pnA{>Q%-bHdku#=Ypcd4B3P zEu%3z#e8Yyr(-I)DTS9fHw&cMV!tL5)&HMYhY0{)-3X5@??cRq{=iOF5V9nJ87t;plt>jm*i(&`z_mo1oNpZBOBCfNWP zDb7BHqQnVJBq~b>;-@{?7LYftTUh$f_`@(hxxZ5i_DPEb`xq*n0Jr z36IsafTay>nbLpn7o$+A`o*7=ge2M&%Wm#T8=PKAS%4B6pjk+J1Vex{JOQST5tDK?mQ+@Gw6oyg=N;w`a@n>za=xa5-M7#ptb@Xx&t|y zlopLT8WB~+5FS%;6yKUT^+OpTtmE+cPX=u^=p}JW!4W#kImOSzf!{XHO>BmFRt8 z*UAU{d{lll-2`OM<$@rgnIS)wk-5-cbE4BhDV}pqoeVtpn&!Vo+duco@c$oUQACz( z<)z=|jFdXWaei$jZzelD#E4ptaQB1m0^+hmbAR{X4D3a(SP;`_YJ_jKe2L_1OtKm3 zjuOmm9JWOLN9GpJnqds1@4noN&((Crh(=5%aKyLsDlm!7DX_)S(Y|Ay8VUdLbT9Ru z%~p=S!yyvMVz6nRY8M{t2S?t0rQK29_ZNLeyWIRyA5PIuS$|#h%zIg~kkE6D_Opp* zbqB71LvL`z3u6E`@fWa0;vwU8}Oofe%10)nVC@A>^){wCgd7os-|JPOLnqv!m) zl=;UeHb#6rjE^hBL;I)ofs<-1`R7Lz-T>zJ*-eD8M@CrtUTADN$o`VNkCZo8&wO4QOqdaGNe>?4g^ zc(|8@J*CP|if4T1HW7BSd}I(H#|2=8HauhzH9qPqhoe73SK(8)-YiPLvZOe8@o+gg z&*!u?pu7yktFWctj{o{~wg%L2%F)k5&HyBKH2cm?p%mc`9bn}iGv!*n=Y`02B_pZl$q7lW44+O`H9mJ80A^81G~D$FSkB&0QH$gtn< z>Li=zEZSw|3u&pRJK|90MkF>{ThWkJ_I&AM~Ajp!#fxY-d+ssj-@=8L|k{fxjlg*kVxCW>e{-u<@_4%X(LZN zNR5)dI#eFL^+DK34AC^;&K8Gx@ni#^V=peaDVCBbiP-NIN3rSY0>2GqSH@8;t+BU5 zqT%ucNu7;9A9G=!GwiUjnpFbEGeuN|-r$=|L%i=)?-H3+l=$Gs3(iG$cZ z>O9qBJCVwu4+T-AF}dP=Kt;QRMPCq*owPd?Y%8r6;c_4582T?fn-DEYn1C_WpXzve z=Ptxg4>O2WY5mu=;zCn>#}?v11-!o*EoIocfDVS(wOF3|H_!M8-3ySY!oO3a9WVGR}5LdOkbAchZ>v)N?t z8WOEKm0UKl=_WZxV9AyG*8GD4eM@@}@OXqf0YL8E{)9;8==3#%9ut zPULOcYlX)?nuoT+qFIADQ*X78=>W#_hCN^U3!u}UIVkbDGEQ<7b3vDhRp|_(6-vM~ z0R<6RV~$zdKv^))vNrVs7%4^<9?p=(fhxhuNn)RS&|rAi66o)z|Kbz~yV@$WDHfW;H% zBeIWsKTUS{=bksr<73>ETV`wC?iik)KM}CM?nD1;+hvJ@Y7Ec@Z@6)Wg7loB6bb&C z3ZvYbvLnM@PFfMH!XI*obL2RVV z7kgWj-J=CkBW>eu60&L*DTU*ijSH`$nt&2n+_E;4P02QG$&fc_P~Nkp~-K3hT4Iw6690lm61gm zyfk$8@II9BZJ0P4JVj;)QB0C!!0qORmhwGwl9FLzIYY7`i2ts6VGa_(Dzw zsKF!O2m=*RfbKh*Dh=PnwUuCrp&ypU?g;lcFG=+rz^cf|JdZRI=Tp}!PIIt&(H9Q{ z8wJPm@ozBnIB6`mcek!HXr5&J${DRP++#!(5goU49ou&86Z-CNQC84i?x%U^$)nyl z$h!@iWyZH4L7!K}LT3DVxQaFA%cC1B86!VJ-b|?iS!c5nhAilci#SjLCUUC$uUPKO z;Us+NI=g7?^cRKPrM2K5#tUK5q=>m0tdJTPPoe4T)6B+r~R_}nDA z6@VH$>E1SZ^{hv=2!cYQtjdJUaYoop@WZ<+?yv7O^7pNcVw z<`6_r6S{A=JtT)C@&(7saf+%#qe~r>08sS;4k!!=lFO259vJ#Y8SIsCH>YS7-Y%Az z*RF;56R6|VS)5D0(7nx9bl3DZA$gjJ^8L(zd*k(y49jU{hC;#wz^$!X0Awpnkn;Pu znoY1@sIY+ayeT=lc_+BkE-Y`!jDBg`9B#1xyP3Bs&~^u|rYWT7L&<5O9rp`oQyV%j z*9+TH%Zy=I0z#p2yb>VqL8ys}w#5FN)9Qk;j_Ko%@)Z{t<(?xmNGL@`K+tzqYJy=m?;c2(!-=Q7>UcoqT4WW0k`8nO3bSTG>`))f2ve$k(OTOZ&OX)6AlLM!3G?-*IRx{NPi+Jzeaeq{?`cUAW=-;IZu+zos%@Ku66s`*aKm~`5a z=6|^;{LwNYJ~mAdD`^rj2iJPZR8Z>cKo9bZbnFN^E@63b!Z3cWe6;h?4J(lMahcVB zp#^xOrU3?eP+6p7PvyrC8P8RC`1z)Riix|Do=lmdJm>ELVPyW&&1;u)j+E2>_6$8} zF7o>XsE^yhD*b3Q;QSYRtSDNM!qtgc?U?p%9#EA(wfRlw$6*ju_=lB)^7>0cv*q3^xDfJHmK;3mn z8+O8_w<*oQCkW1IwxvoN={1iPm_HlqKGD~$`lrG(anHIZ3*0-_6EFjGnLY6}`%NX9@J=d(i>-_o0F%Hj}I)(@iSRr{&-uUCTTuZv~! zN{gce9OEe%*fK2+n4+-j(4BCFkUFle97njc5`NWxu3_Sid7hNGiVBs{JqP-W}v z*j{Ecfozo~`*c4yx=OSBRnt4GjI8DR@!!5#2Cu5=!R%8ZJBmI&AD7^W!fx=5yXqgS z=;NOzJLf&9=_p`LP4-eCkMasHbxHQqF2yeTto%bKJCI7=>~aI+Wp1uljsCj+XL#rg z#R`DgWGjzyouy^J{4}qQl{L9Cr2C5-u_7F{>bu%>E4~bkB(*n)p23EQ>gV(#uxdC}Xx{C`%!E zPg@2#26PsM+P8MyX_-P@Z_Qg=HgR1A;B;^SncHWDikU_suVgZRE7(U%A zt|aXT9Qmotv%XkxitTd`+1`z-sSN;Mq3O7m1LzNu*!yBQ5>nM zxn$(zpq>vB5N?WjfGRl?G{+)ZRJYmJH<4R@_J(fEtVG|^t&srG=gD>p+=@(G-@S{` zSXUgWGCrOc&OAD%*HBx%hoc}NK!5GQPw^{~)CU(_AsLT^@SZHg+4^a3xy6n^CTR6;pfpYiLrfW`(HqXrLpKu~Ms|*FiTZu( ztIkDRRhC_O`CsaJ>Npqo6%6GxJzzRVJUv{XaV6)HXJX4Pbw>IQ+H@+%QIGYo{5hZBTp_ zn0?G*x#Cp|@6)_TUi)v}crvG0gaR_s)(_>SE2RCWPW3iJCI_nm&ZW&!liX%za?Oe3 zmM~sEI=yNLeWFCe5z;?!AY-IRCi&KL^o|Ewacu>N0<46i)mQTUF}@!*bg>S5ogT6sq zRMuQ%x_afa6o;6XAV6dIB!IvU>O>r?da~1@<%(x&O26~f5{;#>o&2myO{hkdO#LKc zId-3!g!UbEBT_v-^w&5o-_q@k1#77sK}b8g|J^;Eb0f+IQ_Y>&S!fv>DeHK=AA zPc^?NW2G}-?CCDz>1mV!q;eC|GOm@zv{&pbnOtsYTR z)6P4^(%SSdIi-NI(?fRD>?{)?b+yyWdvlv-9v7$T(^-y^K`X)K#4se7z9f2 zZr1Y?@to}S6zdj3OJ%{GFk=^v7HvxCIci}wJe0wFc}yicOwMKgANoa9UV=GycQX~Dn9ls^Dvm5EULc%~ zFo%H$kz(QGz%fasi6c4=142!_o}C8`ojoRj|5Ssjk=gUoV%h-EA6Sh*)7tMJsxbSq z7nN3@A*|)B%2ya4UkfY0d<)?qZ|-t({iqWAPxCM9)$L>Oj6#6bfpjKDo1fi-1s4_D z)#Kc_QnUN#Ovk;?aODKFJrCUG;1SwgZP4u`&ZFM69sLQE1X9&zgdyj#--Kaxx#uZZ z|5YsD!-tL&Ou8HMzjH(7<`~XZbGxLocH4$3S#rPe6Ynq;E)a)N2OJ&)+j&COFfqzK z+j?ruF6S4>@OcdQ?!kT*7p{`?O05c)*(^fD!S%*$kpl`DHb7E5pA{t58lbGU$3q2# zf?SX~G5~p&JzU;N!?pK;ET}n+Hy4e9-bNX@MJY0xd6sn!$9jdASmYD8T+% z`mH=a)OnJh4!m@%Kuua(cc2blngR4_c5vF@%(m_qw!&YlxADSK6oH$-?ga+8B0~); zIGp~Zv<^F?U^Milz4ueimTe$iaJldR2C$EbV0D@6fAW+%nT$*pHE}1~K^ziHCvS=n z(`KJo#0^?{#clFAjlb@CGtaJj2yK&uBl|N*U`SSaXQ@5Qn62>Gj60i1n??Mt4LOiP zo51*XuVk+W^Mk=xx>;zcSkB=j_?#i59FD(UagvsMQFaQMo6M;D6J!XTg{zL*5#RUm z^j!;axdo^8$=I%71~+_tk8YY^q=4jy%oc}4H-Oqnk}L_NDpgA4zHv#%DTVgg`s_4v z3;HvkOJpZg!BHf!GCYZ3-&j83@=-9iZ2v+dyq)yIC3F>?rddy;!hvR+j|)<~_yDeCn=`9B+rnElo7yz7N6YdDRl{XjeB4sr8~ z$!zN734Vu&_tdpwyh$QZ>qJqu0;a3<`d7Ef1j_3xur^tP=drw^{+AVP3thAI129_Zr*OXokFSZ4X140@Gm_c0czpnV1 zy(|?UaSq6o4=7RBW?l*H&x|KZDEpiT>U;o*9LeoWAd9Yw zda3v(LR5t<(sW<-7~EnumOss|1SNe3R8%+Uls*OyoO2Ejtfyu-@Wv6`|MA9W>?Z*t z+H-CBiCGM?-7xCj+_-<+M$XtJ)D69oiXeL%7-1UWy9Qi=Q!oF++`{pR{Ig&EssnrX z+cpi@_gTc<( zVs_Q8H+vs;mYH&G*TLt8E$cgTLF>g9^~G|wVAp~?_KOoRxb9Y9a1(Mc2dl3BZ6e2et8Ds^LEbeADD5?+JGZaMN zJ>>r<#S?C(phueWEv+eD0C4Yc=PXIk#m4C1e^!RAKPuoAKdna^&)+ z-7~|1ppByTI+s@NS;Gg*O&Q4T2Wy@+cJxKWby=UsLDOX*cnng547c*?#iIZW*+*=N zUHol0wrXwX?Wk3mdLDH4n`je5KnpeW(p;^+$H)0~mg#kmEk2bOPi!dxHF1suy|QD1@y2CCPUar43zPGAw$idDG>GTg>H zqQz+-`+VF?Evl$KDL+vDbs8SCRU0h14NJ>6jk6fc^6~Z?=PwlJ1~idQFR)dPzyXaL zlXupXs}XEiPill4B_5gA0bhWrr*cLrS_bkni`Og=)c-TivmIoh>{Q<9V~#@yd7ngM zC~alKmD){+CZI~1Ed$w^#W~}J0xNGXRL~HtN*$DXvpR)sr`d}_}TTX5xo>u}kMvtz!QiY=8BzUyN zF~!_a13+_bio@zHFn`z2mYFrAvu<9U0&bpG!4agmO#R1!o;s#+0YshjZIAN1%HPgV zV7<0(;uS={IltsjDr+CewF(j#mDuYsf_eoaDRKm0RKuXhh0lsXf3}P)uoX)7;D0h> z8PgO{l7NEWtmv&~%JY8_WDgi$s=5=*y=35fOORaPXsF^c{B7RP|8jaCCecKm?F^y~ zqIOl8qC;f$?~|8md>ih`d`-Hqd-V0$vT&8aXMYk_ONA)x;T-;@xA?9!o<@pAD2se> zk5PnJ&z8_^cTeyd$@MxgJs<;f7Oh$rqm%D^;p!d7^6qGK2aR)ryZ>{ez_1pXdSo$E z1`;S$fCldB9Fz}V5CkQa!OoX_Y854wi<=tM0lbJqR}&~rJ7_6I=~k=N{@*lfjvcmsF3 zHA~8#-6I86=Eu!5d2LDig+A{n( zEJhM>A;fx*p#D)i{JYGe^Bt4Vd4`{=(ddV;Hd)Xe-vNbqhcg)7T>k_^cjjKhe>l3>LhRu7g4>A zI*#jYHRo?QcpXB?x;9YL5FG?HG9NF_B#qbVGo41hU(8bY`T(Q?^aLya3-yu+w=I2J z=z)(bKq%1FWYdEuGG))RM=(%_GIG70R?799;1oH;r>%s`-^cYnII-1fI|Da8U-a4X zXGpi6GXTa6YCg_LzO*t_;%VVsZg83sC>#BrHWaHMqTHY6cYtw|k@RjE1l#cr)CGqz z4*coX8Ncsuc0y%YpF)}P;2d9=?XU@=W*Kjd9r&RVCK5iJ#gVM9BXKX=Ud~{E4s@h_ z)-Rf{KC^p*a@`5F$@BCSLGbs@aaIb&w25Yf=n#j2YuEJ_zx>DUHwlF%pD?)sE1R^O zw=W)&6JMFF7Y1f&2OS=1w_5%FGQOGjaC_v+NAFge7b=`~@xB7WO%@DF?{ZTlzj3eb zVs;@)fGj8rRfRh({t=9a*6NfpAnv4bN-+>EbEbDC@EDUe*SE@gdGAd1CHFVInXKW=Pni03d`Ih_7Oyn`O10&@ z_1A-7tUjt#Ba%S|+DYV;Y{<}Tz6IXLQ%GZ2QuSNl&F&eU$mxISINnyX83E>TuMgiS z?vv;nLqCW0IY0@FH`0@SM3t zfVXTVA=TFB1+2Q0UthAz;d=$D2(uec6c1T&9YNkH+G7>PnVe zTV*WTP$1C*)$NyE=et*apxSJD%94A~mFOhU4QHBX8(=_un%;WTN>Xb;X#9RABWO06 z_uB>7=xDPoE%wE#t`Q6pPTe$%Ep6E^&#E&Y8SM^ZwU60zKS91GNYB6dP}@Cra=Cjn z`O()1ZbFIkbY&uJrdAg{}Gdm{8(lW^z-d{xs?z*;BZebz5a0OPff4!ID(;Yj$L?%UCvn% zM-lCqv;|;35eI&Z42ZKW*rDHoPdufuxJMCMo)qRDiP5+za_1}7T;bSV0AAXHV0Gm39D}2Cr3bnl5J2j z!Rq2Eyo*LZw}I)pdF@M6oQD)EAs=|Al4j?Gxz)0^1*-8s?m$yAbj^l+dQ=N#WbP#L zo)u3pS9Don%Dh~2iXf|dwqC*c^SbF5Kn zhMIrnv&AT1rDNRXZk|96XJzzreNM|jG}>||9Ca55E;4lR=LrzVg(;Gex&AEYxrIIK zOxCq3`LWE4a3>$JZcHcakD?ii&un_^KKbmM3 zfQS+;p4~v`{>W2DRP~-7mxITIem`8!u}MGf?WC?UJ|U*g`*=B(yvfmK?{TXaW!RCyyO{hOu!FKgOPL=jAmIjG?uOK+KA} zkjG1!XrEyQrSkmMc;DZ3>g}q6$7u#Mnv;eC)z66`KK(nb8l;01f(@ZLfwBU=cLcI$ z`nJ*TI)ctr3}xk@f8NE_g9g3V(N$kMhuRl-kQmbwk0?XycYau8ZO?j zX0F1WuVty~((RQ!7=TQkBd%bcQ(z)mb>5wrNj|xrVR2b6s%K)SQ~mW z!kX;ciTr26wx!|zxMnlCp`^G>W=6(?t!}8Q+Vuc!Spb}pwhHpKOw(O~L|(bnN+zA3 z_&Egd%Y2O!owD0buhhtno1#XaM3biae)551>xALrEX^ifudl2Y^`eN(+tGQ)eNa&0;co#KlNbdl* z&6Mcw2Rs7hBqosy%KO|5rovn3;sTE~Fvh(>o8~8mTHKlagqAw0(?^!;=)X^S|7V0D z(!aQ<70ym5vjDSwE-zL~`H}%lLw7j&9Wt@&ecqNPl4aNe8qjgB)?^QpyG+DHBu+f)zb*~PhKqKWXDhxK`;;b{K5r<|Z3EwTy@`{)@59xDV)q{U56b7;WxTH2N;bQJCVN!?An4Si#8+zCX8@+eE8{6?bbF4*MP` zH2tY_jOUDGBxir0IE{}Lv4HAwKh;6Vs=zO~5}ONRZ8(PqTuWT5`GI(4y_LAX-+`>`&1~fWnVRKn9r@w78qwHsO-ApV&Q8br&SYwSks)VV7vv{zv z6}wgnQ3h{pZ9y>;=NjV4c1R+VwwaCRnF8DuwLN{CVh>yuH1WxKasfx*%dQ1)R4cGm z%wR=3HOVODIa;DXIjcEYXZFkp(OP=%CQDmC5D1pIMa# z5N913-oSxtZ3YVHKv5kq+Df=h7EB)xXw;VAIF-OjqG4D;O2~beOi}=8Z4Zjh2U^{` z&Z^u2wUtl9S+8{~&1fj0n$w8mm7HC7-s)*|2F;_y1K%lA4XW@+o6Bmz9~6w`+8xcRokln98w z{aWU8X6eBm9pJ;sO;ylE;~?vt?=Sa9>O3NP+dRRM;nvR|*%(SZ5S(5f)NqHg!_J(t zj->~iHo3dbkz4W5#@m$JG_Z?pB!?J7K`3LS&iepo&VfYQ0bokx(8b;C+Iw3W2^{bq zKznMFH_i=*&4!>VS%jL~28Pc;XlF2s>@Eou903%(2anB)1a2JsS%IT?z0ZKmWQKwu zr7?L6bcD_Gbd>^{HrO<96RqkFdXiu)wU~rFUc=uyAVMijmV{MJ;1oB;TjWchX^APA zRk#=j)kVjXJM2MHYv}~-1Xof3@gpBS8hvpi!kY`(S8t!m?Eip@6lnLL`+O#D^_lDO~4x zrO?`s*MecEJ;bn5zD}IpXF(AeU>y9!fWJc|O@tEGj5XXMQmrtD^uj0}CW61cv&0p4 z@8d?VhfLrm{;b;yu(p|39F@h>0AH~m>)}}r-)t}h?tM!w$+F;H@Nl!U%NdmKb%9Y=l%hR%R){jZ zVdTQko)t#ayU%$dYZnZIoBCjUEeeM<@k=?rO?fYOc0IJ(N^S;!ZXoQZ=h{Xj=1j^K z_M@$bfDo_m`SCf^IS7{<#Y(V%b~;yKt@``4K!lxF*&@RRml*J8TkJ4_r)U(h$g@~7 zldN?Y4{*%_jQd0js&nV!d$Tjt>Jkay{IWFKMlgjWhi$`%;@Rqpn_XLItK1{f^DNzL zMuN_GT70$t@}{w`wj3a4Jg>XidD~8XWYs;sIV^H+c=x5?eTuM-Kl>{*B z%-eSz$ijdqf+zZ%N{IplC2$vv{3e1nXC7y*F}aDV0{$XKk6hx{n;_T#+X=uu5F!QV(&GE~ zR&E$9aqt^z38Rht%WFZ1LI*n_4$1v2;nd1NJJNVk;L+RruoE2gMdif< zOoJalLfBx8_H4^vTG#%M#c0>)+0irph;K#jx`3dg>{hvXM;9mez0I^Tr0ptM2?uMq-PyrvXfD6$4c#!$^ zZ=U2o-rFFpetF#}+Y3oK;zLKu2!*t>Tcne32U{^mc>g2HNl0+3*rH{=MD*-{gt)7eHQdI1lkWhzU${NiH{_F~`8va<8WN7R1FM u&5Xc>0Fd;+;MmpRDVPY(TWcTvXJ7tOYN^=F$pJt|F?hQAxvX Date: Mon, 5 Jan 2026 19:56:03 -0500 Subject: [PATCH 62/67] Add files via upload --- metadata/en-US/full_description.txt | 15 +++++++++++++++ metadata/en-US/short_description.txt | 1 + metadata/en-US/title.txt | 1 + 3 files changed, 17 insertions(+) create mode 100644 metadata/en-US/full_description.txt create mode 100644 metadata/en-US/short_description.txt create mode 100644 metadata/en-US/title.txt diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt new file mode 100644 index 0000000..78e3e67 --- /dev/null +++ b/metadata/en-US/full_description.txt @@ -0,0 +1,15 @@ +Auto Off Bluetooth + +Auto Off Bluetooth is a lightweight utility for Android designed to preserve battery life and increase device security. The app monitors your Bluetooth connection status and automatically turns off the Bluetooth radio after 20 seconds if no devices are connected. + +How it works + +The app listens for Bluetooth state changes in the stack and for Asynchronous Connection-Less disconnection events in the background. When a device disconnects, the app starts a timer. If the timer expires without a reconnection, the app automatically disables the Bluetooth adapter to save power. If a Bluetooth device reconnects, the app postpones the Auto Off task until the next disconnect. + +Permissions + +The app requires the following permissions to manage your Bluetooth hardware: + +* BLUETOOTH: Allows the app to see the status of connections. +* BLUETOOTH_ADMIN: Allows the app to toggle the Bluetooth radio on/off. +* BLUETOOTH_CONNECT: To interact with paired devices (required for Android 12+). diff --git a/metadata/en-US/short_description.txt b/metadata/en-US/short_description.txt new file mode 100644 index 0000000..9dc90c7 --- /dev/null +++ b/metadata/en-US/short_description.txt @@ -0,0 +1 @@ +The app monitors Bluetooth connection status and automatically turns it off. diff --git a/metadata/en-US/title.txt b/metadata/en-US/title.txt new file mode 100644 index 0000000..e326e10 --- /dev/null +++ b/metadata/en-US/title.txt @@ -0,0 +1 @@ +Auto Off Bluetooth From eac1b4b5c0ed78664043d2e53d56ed4dbcff06ea Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:04:45 -0500 Subject: [PATCH 63/67] Add files via upload --- metadata/en-US/images/phoneScreenshots/01.png | Bin 0 -> 20831 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 metadata/en-US/images/phoneScreenshots/01.png diff --git a/metadata/en-US/images/phoneScreenshots/01.png b/metadata/en-US/images/phoneScreenshots/01.png new file mode 100644 index 0000000000000000000000000000000000000000..1b206fbf067789151eee640ed02caf2a617e0876 GIT binary patch literal 20831 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 literal 0 HcmV?d00001 From a2ae26fa74cd7b12cda851d7d1df5745981c429d Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:05:12 -0500 Subject: [PATCH 64/67] Delete metadata/en-US/images/phoneScreenshots/read.md --- metadata/en-US/images/phoneScreenshots/read.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 metadata/en-US/images/phoneScreenshots/read.md diff --git a/metadata/en-US/images/phoneScreenshots/read.md b/metadata/en-US/images/phoneScreenshots/read.md deleted file mode 100644 index d00491f..0000000 --- a/metadata/en-US/images/phoneScreenshots/read.md +++ /dev/null @@ -1 +0,0 @@ -1 From 18e35776dbe6cdae1ae3d9bac03b60c4809bf756 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:07:03 -0500 Subject: [PATCH 65/67] Create read.md --- images/read.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 images/read.md diff --git a/images/read.md b/images/read.md new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/images/read.md @@ -0,0 +1 @@ +1 From 6cbc9daed2bdfa30a49d144367c92bf26eaa58ae Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:07:33 -0500 Subject: [PATCH 66/67] Add files via upload --- images/GitHub.png | Bin 0 -> 14845 bytes images/IzzyOnDroid.png | Bin 0 -> 20021 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/GitHub.png create mode 100644 images/IzzyOnDroid.png diff --git a/images/GitHub.png b/images/GitHub.png new file mode 100644 index 0000000000000000000000000000000000000000..9082d22aa440fc6cf099a380cf1988e2edfa2f80 GIT binary patch literal 14845 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 JLh9*@{|BXm0(t-d literal 0 HcmV?d00001 diff --git a/images/IzzyOnDroid.png b/images/IzzyOnDroid.png new file mode 100644 index 0000000000000000000000000000000000000000..cb10c3a04284e5f7a6da7c6d7cc1bb343b812ae0 GIT binary patch literal 20021 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 APyhe` literal 0 HcmV?d00001 From a360c7c9847d988b399e035040d9bb9084a166e0 Mon Sep 17 00:00:00 2001 From: The-First-King <59452275+The-First-King@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:07:50 -0500 Subject: [PATCH 67/67] Delete images/read.md --- images/read.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/read.md diff --git a/images/read.md b/images/read.md deleted file mode 100644 index d00491f..0000000 --- a/images/read.md +++ /dev/null @@ -1 +0,0 @@ -1