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 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 }} 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 diff --git a/README.md b/README.md index ca94c59..73775aa 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. + +--- diff --git a/app/build.gradle b/app/build.gradle index 0078838..a3433b5 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" + applicationId "com.mine.autooffbluetooth" minSdkVersion 15 - targetSdkVersion 28 - versionCode 5 - versionName "1.4" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + targetSdkVersion 31 + versionCode 6 + versionName "1.5" + + // 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' } 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()); - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 164027a..5141865 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,9 +1,11 @@ + package="com.mine.autooffbluetooth"> - - + + + + - + + - - + + + - \ No newline at end of file + 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(); + } + } + } +} 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 24fd979..0000000 --- a/app/src/main/java/com/mystro256/autooffbluetooth/BTReceiver.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mystro256.autooffbluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothProfile; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -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. - @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; - } - } - // This point should only be reacted if nothing is connected - BluetoothAdapter.getDefaultAdapter().disable(); - } - } - -} 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 fb0f2c0..0000000 --- a/app/src/main/java/com/mystro256/autooffbluetooth/MainActivity.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.mystro256.autooffbluetooth; - -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -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; - - 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(); - } - } - } - - // 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); - - WelcomeText.setVisibility(View.VISIBLE); - batteryOptimizationText.setVisibility(View.GONE); - batteryOptimizationButton.setVisibility(View.GONE); - } - - @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(); - } - } - - public void disableBatteryOptimization(View v) { - Intent intent = new Intent(); - String packageName = getPackageName(); - - // 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); - } -} 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 + 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 diff --git a/build.gradle b/build.gradle index 9313af6..e970f21 100644 --- a/build.gradle +++ b/build.gradle @@ -1,24 +1,17 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { repositories { google() - jcenter() - + mavenCentral() } 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 + classpath 'com.android.tools.build:gradle:7.2.2' } } allprojects { repositories { google() - jcenter() - + mavenCentral() } } 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/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 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3eb1008..2ec77e5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ 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.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/images/GitHub.png b/images/GitHub.png new file mode 100644 index 0000000..9082d22 Binary files /dev/null and b/images/GitHub.png differ diff --git a/images/IzzyOnDroid.png b/images/IzzyOnDroid.png new file mode 100644 index 0000000..cb10c3a Binary files /dev/null and b/images/IzzyOnDroid.png differ 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. 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/images/icon.png b/metadata/en-US/images/icon.png new file mode 100644 index 0000000..22b9a95 Binary files /dev/null and b/metadata/en-US/images/icon.png differ diff --git a/metadata/en-US/images/phoneScreenshots/01.png b/metadata/en-US/images/phoneScreenshots/01.png new file mode 100644 index 0000000..1b206fb Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/01.png differ 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/fastlane/metadata/android/en-US/title.txt b/metadata/en-US/title.txt similarity index 100% rename from fastlane/metadata/android/en-US/title.txt rename to metadata/en-US/title.txt