11package com.example.microphone.streaming
22
33import android.Manifest
4- import android.bluetooth.BluetoothAdapter
5- import android.bluetooth.BluetoothClass
6- import android.bluetooth.BluetoothDevice
7- import android.bluetooth.BluetoothSocket
4+ import android.bluetooth.*
85import android.content.BroadcastReceiver
96import android.content.Context
107import android.content.Intent
118import android.content.IntentFilter
129import android.content.pm.PackageManager
10+ import android.os.Build
1311import android.util.Log
1412import androidx.core.content.ContextCompat
1513import com.example.microphone.audio.AudioBuffer
@@ -26,7 +24,7 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
2624 private val myUUID : UUID = UUID .fromString(" 34335e34-bccf-11eb-8529-0242ac130003" )
2725 private val MAX_WAIT_TIME = 1500L // timeout
2826
29- private val adapter : BluetoothAdapter ? = BluetoothAdapter .getDefaultAdapter()
27+ private val adapter : BluetoothAdapter
3028 private var target : BluetoothDevice ? = null
3129 private var socket : BluetoothSocket ? = null
3230
@@ -51,12 +49,20 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
5149 // init everything
5250 init
5351 {
52+ // get bluetooth adapter
53+ val bm = ctx.getSystemService(Context .BLUETOOTH_SERVICE ) as BluetoothManager
54+ adapter = bm.adapter
5455 // check bluetooth adapter
5556 require(adapter != null ) {" Bluetooth adapter is not found" }
5657 // check permission
5758 require(ContextCompat .checkSelfPermission(ctx, Manifest .permission.BLUETOOTH ) == PackageManager .PERMISSION_GRANTED ){
5859 " Bluetooth is not permitted"
5960 }
61+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
62+ require(ContextCompat .checkSelfPermission(ctx, Manifest .permission.BLUETOOTH_CONNECT ) == PackageManager .PERMISSION_GRANTED ){
63+ " Bluetooth is not permitted"
64+ }
65+ }
6066 require(adapter.isEnabled){" Bluetooth adapter is not enabled" }
6167 // set target device
6268 selectTargetDevice()
@@ -77,13 +83,21 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
7783 } catch (e : IOException ) {
7884 Log .d(TAG , " connect [createInsecureRfcommSocketToServiceRecord]: ${e.message} " )
7985 null
86+ } catch (e : SecurityException )
87+ {
88+ Log .d(TAG , " connect [createInsecureRfcommSocketToServiceRecord]: ${e.message} " )
89+ null
8090 } ? : return false
8191 // connect to server
8292 try {
8393 socket?.connect()
8494 } catch (e : IOException ){
8595 Log .d(TAG , " connect [connect]: ${e.message} " )
8696 return false
97+ } catch (e : SecurityException )
98+ {
99+ Log .d(TAG , " connect [connect]: ${e.message} " )
100+ return false
87101 }
88102 Log .d(TAG , " connect: connected" )
89103 return true
@@ -136,22 +150,28 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
136150 private fun selectTargetDevice ()
137151 {
138152 target = null
139- val pairedDevices = adapter?.bondedDevices ? : return
140- for (device in pairedDevices)
141- {
142- if (device.bluetoothClass.majorDeviceClass == BluetoothClass .Device .Major .COMPUTER )
153+ try {
154+ val pairedDevices = adapter.bondedDevices ? : return
155+ for (device in pairedDevices)
143156 {
144- Log .d(TAG , " selectTargetDevice: testing ${device.name} " )
145- if (testConnection(device))
157+ if (device.bluetoothClass.majorDeviceClass == BluetoothClass .Device .Major .COMPUTER )
146158 {
147- target = device
148- Log .d(TAG , " selectTargetDevice: ${device.name} is valid" )
149- break
159+ Log .d(TAG , " selectTargetDevice: testing ${device.name} " )
160+ if (testConnection(device))
161+ {
162+ target = device
163+ Log .d(TAG , " selectTargetDevice: ${device.name} is valid" )
164+ break
165+ }
166+ else
167+ Log .d(TAG , " selectTargetDevice: ${device.name} is invalid" )
150168 }
151- else
152- Log .d(TAG , " selectTargetDevice: ${device.name} is invalid" )
153169 }
170+ } catch (e : SecurityException )
171+ {
172+ Log .d(TAG , " selectTargetDevice: ${e.message} " )
154173 }
174+
155175 }
156176
157177 // test connection with a device
@@ -165,13 +185,21 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
165185 } catch (e : IOException ) {
166186 Log .d(TAG , " testConnection [createInsecureRfcommSocketToServiceRecord]: ${e.message} " )
167187 null
188+ } catch (e : SecurityException )
189+ {
190+ Log .d(TAG , " testConnection [createInsecureRfcommSocketToServiceRecord]: ${e.message} " )
191+ null
168192 } ? : return false
169193 // try to connect
170194 try {
171195 socket.connect()
172196 } catch (e : IOException ){
173197 Log .d(TAG , " testConnection [connect]: ${e.message} " )
174198 return false
199+ } catch (e : SecurityException )
200+ {
201+ Log .d(TAG , " testConnection [connect]: ${e.message} " )
202+ return false
175203 }
176204 var isValid = false
177205 runBlocking(Dispatchers .IO ) {
@@ -215,8 +243,15 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
215243 // get connected device information
216244 override fun getInfo () : String
217245 {
218- if (adapter == null || target == null || socket == null ) return " "
219- return " [Device Name] ${target?.name} \n [Device Address] ${target?.address} "
246+ if (target == null || socket == null ) return " "
247+ val deviceName = try {
248+ target?.name
249+ } catch (e : SecurityException )
250+ {
251+ Log .d(TAG , " getInfo: ${e.message} " )
252+ " null"
253+ }
254+ return " [Device Name] ${deviceName} \n [Device Address] ${target?.address} "
220255 }
221256
222257 // return true if is connected for streaming
0 commit comments