Merge pull request #102 from simondankelmann/simondankelmann/advertisingImprovements

Improved Advertising iOs Device PopUps in non legacy Mode
This commit is contained in:
Simon Dankelmann 2023-11-10 17:08:45 +01:00 committed by GitHub
commit a272efcf45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 64 additions and 19 deletions

View File

@ -14,7 +14,7 @@ android {
minSdk = 26 minSdk = 26
targetSdk = 34 targetSdk = 34
versionCode = 1 versionCode = 1
versionName = "1.0.3" versionName = "1.0.4"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

Binary file not shown.

View File

@ -12,7 +12,7 @@
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 1, "versionCode": 1,
"versionName": "1.0.3", "versionName": "1.0.4",
"outputFile": "app-debug.apk" "outputFile": "app-debug.apk"
} }
], ],

Binary file not shown.

View File

@ -12,7 +12,7 @@
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 1, "versionCode": 1,
"versionName": "1.0.3", "versionName": "1.0.4",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],

View File

@ -55,9 +55,11 @@ class ContinuityDevicePopUpAdvertisementSetGenerator: IAdvertisementSetGenerator
advertisementSet.advertisingSetParameters.legacyMode = true advertisementSet.advertisingSetParameters.legacyMode = true
advertisementSet.advertisingSetParameters.interval = AdvertisingSetParameters.INTERVAL_MIN advertisementSet.advertisingSetParameters.interval = AdvertisingSetParameters.INTERVAL_MIN
advertisementSet.advertisingSetParameters.txPowerLevel = AdvertisingSetParameters.TX_POWER_HIGH advertisementSet.advertisingSetParameters.txPowerLevel = AdvertisingSetParameters.TX_POWER_HIGH
advertisementSet.advertisingSetParameters.primaryPhy = BluetoothDevice.PHY_LE_1M // Phy is only used in non Legacy Mode
advertisementSet.advertisingSetParameters.secondaryPhy = BluetoothDevice.PHY_LE_1M advertisementSet.advertisingSetParameters.primaryPhy = BluetoothDevice.PHY_LE_CODED
advertisementSet.advertisingSetParameters.scannable = false advertisementSet.advertisingSetParameters.secondaryPhy = BluetoothDevice.PHY_LE_CODED
advertisementSet.advertisingSetParameters.scannable = true
advertisementSet.advertisingSetParameters.connectable = false
// AdvertiseData // AdvertiseData
advertisementSet.advertiseData.includeDeviceName = false advertisementSet.advertiseData.includeDeviceName = false

View File

@ -26,6 +26,11 @@ class AdvertisementSetQueueHandler :IAdvertisementServiceCallback {
} }
} }
fun setAdvertisementService(advertisementService: IAdvertisementService){
_advertisementService = advertisementService
_advertisementService!!.addAdvertisementServiceCallback(this)
}
fun setTxPowerLevel(txPowerLevel:Int){ fun setTxPowerLevel(txPowerLevel:Int){
if(_advertisementService != null){ if(_advertisementService != null){
_advertisementService!!.setTxPowerLevel(txPowerLevel) _advertisementService!!.setTxPowerLevel(txPowerLevel)

View File

@ -6,6 +6,8 @@ import android.bluetooth.BluetoothManager
import android.bluetooth.le.AdvertisingSetCallback import android.bluetooth.le.AdvertisingSetCallback
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.Bundle 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.Constants.Constants
import de.simon.dankelmann.bluetoothlespam.Enums.AdvertisementError import de.simon.dankelmann.bluetoothlespam.Enums.AdvertisementError
import de.simon.dankelmann.bluetoothlespam.Handlers.AdvertisementSetQueueHandler 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.PermissionCheck.PermissionCheck
import de.simon.dankelmann.bluetoothlespam.Services.LegacyAdvertisementService import de.simon.dankelmann.bluetoothlespam.Services.LegacyAdvertisementService
import de.simon.dankelmann.bluetoothlespam.Services.ModernAdvertisementService import de.simon.dankelmann.bluetoothlespam.Services.ModernAdvertisementService
@ -38,6 +41,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private val _logTag = "MainActivity" private val _logTag = "MainActivity"
private lateinit var sharedPreferenceChangedListener:OnSharedPreferenceChangeListener
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -56,6 +60,22 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(binding.appBarMain.toolbar) 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 drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_main) val navController = findNavController(R.id.nav_host_fragment_content_main)
@ -72,39 +92,53 @@ class MainActivity : AppCompatActivity() {
) )
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController) navView.setupWithNavController(navController)
logHardwareDetails()
} }
fun initializeBluetooth():Boolean{ fun initializeBluetooth():Boolean{
var bluetoothAdapter = AppContext.getContext().bluetoothAdapter() var bluetoothAdapter = AppContext.getContext().bluetoothAdapter()
if(bluetoothAdapter != null){ if(bluetoothAdapter != null){
val useLegacyAdvertisement = getUseLegacyAdvertisingPreference() val advertisementService = getAdvertisementService()
val advertisementService = when (useLegacyAdvertisement) {
true -> LegacyAdvertisementService()
else -> {ModernAdvertisementService()}
}
AppContext.setAdvertisementService(advertisementService) AppContext.setAdvertisementService(advertisementService)
var advertisementSetQueueHandler = AdvertisementSetQueueHandler() var advertisementSetQueueHandler = AdvertisementSetQueueHandler()
AppContext.setAdvertisementSetQueueHandler(advertisementSetQueueHandler) AppContext.setAdvertisementSetQueueHandler(advertisementSetQueueHandler)
return true return true
} }
Log.d(_logTag, "Bluetooth Adapter is null")
return false return false
} }
private fun getUseLegacyAdvertisingPreference():Boolean{ private fun getAdvertisementService() : IAdvertisementService{
val preferences = PreferenceManager.getDefaultSharedPreferences(AppContext.getContext()).all
var useLegacyAdvertisementService = true // <-- DEFAULT
// Get from Settings, if present
val preferences = PreferenceManager.getDefaultSharedPreferences(AppContext.getContext()).all
preferences.forEach { preferences.forEach {
if(it.key == AppContext.getActivity().resources.getString(R.string.preference_key_use_legacy_advertising)){ if(it.key == AppContext.getActivity().resources.getString(R.string.preference_key_use_legacy_advertising)){
val legacyAdvertising = it.value as Boolean useLegacyAdvertisementService = it.value as Boolean
return legacyAdvertising
} }
} }
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 { private val bluetoothAdapter: BluetoothAdapter by lazy {

View File

@ -15,6 +15,7 @@ class AdvertisingSetParametersModel {
var primaryPhy = BluetoothDevice.PHY_LE_1M var primaryPhy = BluetoothDevice.PHY_LE_1M
var secondaryPhy = BluetoothDevice.PHY_LE_1M var secondaryPhy = BluetoothDevice.PHY_LE_1M
var scannable = false var scannable = false
var connectable = false
fun validate():Boolean{ fun validate():Boolean{
//@Todo: implement validation here //@Todo: implement validation here
@ -29,6 +30,7 @@ class AdvertisingSetParametersModel {
params.setPrimaryPhy(primaryPhy) params.setPrimaryPhy(primaryPhy)
params.setSecondaryPhy(secondaryPhy) params.setSecondaryPhy(secondaryPhy)
params.setScannable(scannable) params.setScannable(scannable)
params.setConnectable(connectable)
try{ try{
when (txPowerLevel) { when (txPowerLevel) {

View File

@ -38,6 +38,7 @@ class LegacyAdvertisementService: IAdvertisementService {
if(PermissionCheck.checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, AppContext.getActivity())){ if(PermissionCheck.checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, AppContext.getActivity())){
val preparedAdvertisementSet = prepareAdvertisementSet(advertisementSet) val preparedAdvertisementSet = prepareAdvertisementSet(advertisementSet)
_advertiser!!.startAdvertising(preparedAdvertisementSet.advertiseSettings.build(), preparedAdvertisementSet.advertiseData.build(), preparedAdvertisementSet.advertisingCallback) _advertiser!!.startAdvertising(preparedAdvertisementSet.advertiseSettings.build(), preparedAdvertisementSet.advertiseData.build(), preparedAdvertisementSet.advertisingCallback)
Log.d(_logTag, "Started Legacy Advertisement")
_currentAdvertisementSet = preparedAdvertisementSet _currentAdvertisementSet = preparedAdvertisementSet
_advertisementServiceCallbacks.map { _advertisementServiceCallbacks.map {
it.onAdvertisementSetStart(advertisementSet) it.onAdvertisementSetStart(advertisementSet)

View File

@ -55,6 +55,7 @@ class ModernAdvertisementService: IAdvertisementService{
if(PermissionCheck.checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, AppContext.getActivity())){ if(PermissionCheck.checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE, AppContext.getActivity())){
val preparedAdvertisementSet = prepareAdvertisementSet(advertisementSet) val preparedAdvertisementSet = prepareAdvertisementSet(advertisementSet)
_advertiser!!.startAdvertisingSet(preparedAdvertisementSet.advertisingSetParameters.build(), preparedAdvertisementSet.advertiseData.build(), null, null, null, preparedAdvertisementSet.advertisingSetCallback) _advertiser!!.startAdvertisingSet(preparedAdvertisementSet.advertisingSetParameters.build(), preparedAdvertisementSet.advertiseData.build(), null, null, null, preparedAdvertisementSet.advertisingSetCallback)
Log.d(_logTag, "Started Modern Advertisement")
_currentAdvertisementSet = preparedAdvertisementSet _currentAdvertisementSet = preparedAdvertisementSet
_advertisementServiceCallbacks.map { _advertisementServiceCallbacks.map {
it.onAdvertisementSetStart(advertisementSet) it.onAdvertisementSetStart(advertisementSet)