diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 652c616..77aae39 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,7 +14,7 @@ android { minSdk = 26 targetSdk = 34 versionCode = 1 - versionName = "1.0.3" + versionName = "1.0.4" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/debug/app-debug.apk b/app/debug/app-debug.apk index f6fcc5e..56e2bd5 100644 Binary files a/app/debug/app-debug.apk and b/app/debug/app-debug.apk differ diff --git a/app/debug/output-metadata.json b/app/debug/output-metadata.json index d5d8186..047a0a7 100644 --- a/app/debug/output-metadata.json +++ b/app/debug/output-metadata.json @@ -12,7 +12,7 @@ "filters": [], "attributes": [], "versionCode": 1, - "versionName": "1.0.3", + "versionName": "1.0.4", "outputFile": "app-debug.apk" } ], diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 0655d1a..e758568 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 5867827..e26349b 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -12,7 +12,7 @@ "filters": [], "attributes": [], "versionCode": 1, - "versionName": "1.0.3", + "versionName": "1.0.4", "outputFile": "app-release.apk" } ], diff --git a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/AdvertisementSetGenerators/ContinuityDevicePopUpAdvertisementSetGenerator.kt b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/AdvertisementSetGenerators/ContinuityDevicePopUpAdvertisementSetGenerator.kt index f44c1b9..f159279 100644 --- a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/AdvertisementSetGenerators/ContinuityDevicePopUpAdvertisementSetGenerator.kt +++ b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/AdvertisementSetGenerators/ContinuityDevicePopUpAdvertisementSetGenerator.kt @@ -55,9 +55,11 @@ class ContinuityDevicePopUpAdvertisementSetGenerator: IAdvertisementSetGenerator advertisementSet.advertisingSetParameters.legacyMode = true advertisementSet.advertisingSetParameters.interval = AdvertisingSetParameters.INTERVAL_MIN advertisementSet.advertisingSetParameters.txPowerLevel = AdvertisingSetParameters.TX_POWER_HIGH - advertisementSet.advertisingSetParameters.primaryPhy = BluetoothDevice.PHY_LE_1M - advertisementSet.advertisingSetParameters.secondaryPhy = BluetoothDevice.PHY_LE_1M - advertisementSet.advertisingSetParameters.scannable = false + // Phy is only used in non Legacy Mode + advertisementSet.advertisingSetParameters.primaryPhy = BluetoothDevice.PHY_LE_CODED + advertisementSet.advertisingSetParameters.secondaryPhy = BluetoothDevice.PHY_LE_CODED + advertisementSet.advertisingSetParameters.scannable = true + advertisementSet.advertisingSetParameters.connectable = false // AdvertiseData advertisementSet.advertiseData.includeDeviceName = false diff --git a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Handlers/AdvertisementSetQueueHandler.kt b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Handlers/AdvertisementSetQueueHandler.kt index 0d79f77..2bc3d36 100644 --- a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Handlers/AdvertisementSetQueueHandler.kt +++ b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Handlers/AdvertisementSetQueueHandler.kt @@ -26,6 +26,11 @@ class AdvertisementSetQueueHandler :IAdvertisementServiceCallback { } } + fun setAdvertisementService(advertisementService: IAdvertisementService){ + _advertisementService = advertisementService + _advertisementService!!.addAdvertisementServiceCallback(this) + } + fun setTxPowerLevel(txPowerLevel:Int){ if(_advertisementService != null){ _advertisementService!!.setTxPowerLevel(txPowerLevel) diff --git a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/MainActivity.kt b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/MainActivity.kt index 0102ef6..506080f 100644 --- a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/MainActivity.kt +++ b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/MainActivity.kt @@ -6,6 +6,8 @@ import android.bluetooth.BluetoothManager import android.bluetooth.le.AdvertisingSetCallback import android.content.Context import android.content.Intent +import android.content.SharedPreferences +import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.content.pm.PackageManager import android.os.Build import android.os.Bundle @@ -27,6 +29,7 @@ import de.simon.dankelmann.bluetoothlespam.AppContext.AppContext.Companion.bluet import de.simon.dankelmann.bluetoothlespam.Constants.Constants import de.simon.dankelmann.bluetoothlespam.Enums.AdvertisementError import de.simon.dankelmann.bluetoothlespam.Handlers.AdvertisementSetQueueHandler +import de.simon.dankelmann.bluetoothlespam.Interfaces.Services.IAdvertisementService import de.simon.dankelmann.bluetoothlespam.PermissionCheck.PermissionCheck import de.simon.dankelmann.bluetoothlespam.Services.LegacyAdvertisementService import de.simon.dankelmann.bluetoothlespam.Services.ModernAdvertisementService @@ -38,6 +41,7 @@ class MainActivity : AppCompatActivity() { private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var binding: ActivityMainBinding private val _logTag = "MainActivity" + private lateinit var sharedPreferenceChangedListener:OnSharedPreferenceChangeListener override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -56,6 +60,22 @@ class MainActivity : AppCompatActivity() { setSupportActionBar(binding.appBarMain.toolbar) + // Listen to Preference changes + var prefs = PreferenceManager.getDefaultSharedPreferences(this); + + sharedPreferenceChangedListener = OnSharedPreferenceChangeListener { sharedPreferences, key -> + run { + var legacyAdvertisingKey = AppContext.getActivity().resources.getString(R.string.preference_key_use_legacy_advertising) + if (key == legacyAdvertisingKey) { + val advertisementService = getAdvertisementService() + AppContext.setAdvertisementService(advertisementService) + AppContext.getAdvertisementSetQueueHandler().setAdvertisementService(advertisementService) + } + } + } + + prefs.registerOnSharedPreferenceChangeListener(sharedPreferenceChangedListener); + val drawerLayout: DrawerLayout = binding.drawerLayout val navView: NavigationView = binding.navView val navController = findNavController(R.id.nav_host_fragment_content_main) @@ -72,39 +92,53 @@ class MainActivity : AppCompatActivity() { ) setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) + + logHardwareDetails() } fun initializeBluetooth():Boolean{ var bluetoothAdapter = AppContext.getContext().bluetoothAdapter() if(bluetoothAdapter != null){ - val useLegacyAdvertisement = getUseLegacyAdvertisingPreference() - - val advertisementService = when (useLegacyAdvertisement) { - true -> LegacyAdvertisementService() - else -> {ModernAdvertisementService()} - } - + val advertisementService = getAdvertisementService() AppContext.setAdvertisementService(advertisementService) var advertisementSetQueueHandler = AdvertisementSetQueueHandler() AppContext.setAdvertisementSetQueueHandler(advertisementSetQueueHandler) return true } - Log.d(_logTag, "Bluetooth Adapter is null") return false } - private fun getUseLegacyAdvertisingPreference():Boolean{ - val preferences = PreferenceManager.getDefaultSharedPreferences(AppContext.getContext()).all + private fun getAdvertisementService() : IAdvertisementService{ + var useLegacyAdvertisementService = true // <-- DEFAULT + + // Get from Settings, if present + val preferences = PreferenceManager.getDefaultSharedPreferences(AppContext.getContext()).all preferences.forEach { if(it.key == AppContext.getActivity().resources.getString(R.string.preference_key_use_legacy_advertising)){ - val legacyAdvertising = it.value as Boolean - return legacyAdvertising + useLegacyAdvertisementService = it.value as Boolean } } - return false + val advertisementService = when (useLegacyAdvertisementService) { + true -> LegacyAdvertisementService() + else -> {ModernAdvertisementService()} + } + + Log.d(_logTag, "Setting up Advertisement Service. Legacy = $useLegacyAdvertisementService") + + return advertisementService + } + + private fun logHardwareDetails(){ + var bluetoothAdapter:BluetoothAdapter = bluetoothAdapter + if(bluetoothAdapter != null){ + Log.d(_logTag, "---------------Bluetooth Adapter Info: -----------") + + Log.d(_logTag, "isLeCodedPhySupported : " + bluetoothAdapter.isLeCodedPhySupported) + + } } private val bluetoothAdapter: BluetoothAdapter by lazy { diff --git a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Models/AdvertisingSetParametersModel.kt b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Models/AdvertisingSetParametersModel.kt index 72719c1..c04c146 100644 --- a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Models/AdvertisingSetParametersModel.kt +++ b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Models/AdvertisingSetParametersModel.kt @@ -15,6 +15,7 @@ class AdvertisingSetParametersModel { var primaryPhy = BluetoothDevice.PHY_LE_1M var secondaryPhy = BluetoothDevice.PHY_LE_1M var scannable = false + var connectable = false fun validate():Boolean{ //@Todo: implement validation here @@ -29,6 +30,7 @@ class AdvertisingSetParametersModel { params.setPrimaryPhy(primaryPhy) params.setSecondaryPhy(secondaryPhy) params.setScannable(scannable) + params.setConnectable(connectable) try{ when (txPowerLevel) { diff --git a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/LegacyAdvertisementService.kt b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/LegacyAdvertisementService.kt index 24395e0..0b99fd8 100644 --- a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/LegacyAdvertisementService.kt +++ b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/LegacyAdvertisementService.kt @@ -38,6 +38,7 @@ class LegacyAdvertisementService: IAdvertisementService { if(PermissionCheck.checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, AppContext.getActivity())){ val preparedAdvertisementSet = prepareAdvertisementSet(advertisementSet) _advertiser!!.startAdvertising(preparedAdvertisementSet.advertiseSettings.build(), preparedAdvertisementSet.advertiseData.build(), preparedAdvertisementSet.advertisingCallback) + Log.d(_logTag, "Started Legacy Advertisement") _currentAdvertisementSet = preparedAdvertisementSet _advertisementServiceCallbacks.map { it.onAdvertisementSetStart(advertisementSet) diff --git a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/ModernAdvertisementService.kt b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/ModernAdvertisementService.kt index d4686f7..125f52a 100644 --- a/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/ModernAdvertisementService.kt +++ b/app/src/main/java/de/simon/dankelmann/bluetoothlespam/Services/ModernAdvertisementService.kt @@ -55,6 +55,7 @@ class ModernAdvertisementService: IAdvertisementService{ if(PermissionCheck.checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, AppContext.getActivity())){ val preparedAdvertisementSet = prepareAdvertisementSet(advertisementSet) _advertiser!!.startAdvertisingSet(preparedAdvertisementSet.advertisingSetParameters.build(), preparedAdvertisementSet.advertiseData.build(), null, null, null, preparedAdvertisementSet.advertisingSetCallback) + Log.d(_logTag, "Started Modern Advertisement") _currentAdvertisementSet = preparedAdvertisementSet _advertisementServiceCallbacks.map { it.onAdvertisementSetStart(advertisementSet)