Код: Выделить всё
class MainActivity : AppCompatActivity() {
private var isBluetoothEnabled = false
private var isClient = false
private val bluetoothPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val allGranted = permissions.all { it.value }
if (allGranted) {
enableBluetooth()
// You can now safely start pairing or communication
} else {
isBluetoothEnabled = false
}
}
private fun checkAndRequestBluetoothPermissions() {
val neededPermissions = mutableListOf()
Log.i("here123","1")
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
// Android 12 (API 31–32)
neededPermissions.add(Manifest.permission.BLUETOOTH_CONNECT)
neededPermissions.add(Manifest.permission.BLUETOOTH_SCAN)
}
else -> {
// Android 11 and below — no runtime permissions needed
return
}
}
Log.i("here123","2")
val notGranted = neededPermissions.filter {
ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
}
Log.i("here123","3")
if (notGranted.isNotEmpty()) {
Log.i("here123","4")
bluetoothPermissionLauncher.launch(notGranted.toTypedArray())
} else {
Log.i("here123","5")
enableBluetooth()
}
}
fun isLocationServiceEnabled(): Boolean {
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
}
private fun enableBluetooth(){
if (!mBluetoothAdapter.isEnabled) {
Log.i("here123","6")
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
Log.i("here123","7")
enableBluetoothLauncher.launch(enableBtIntent)
} else {
isBluetoothEnabled = true
}
}
private val enableBluetoothLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
isBluetoothEnabled = if (result.resultCode == RESULT_OK) {
// User enabled Bluetooth
true
} else {
// User cancelled or Bluetooth not enabled
false
}
Log.i("here123","8")
if (!isLocationServiceEnabled()) {
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
Log.i("here123","9")
}
val classicBluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
.build()
val leBluetoothDeviceFilter = BluetoothLeDeviceFilter.Builder()
.build()
private val pairingRequest: AssociationRequest = AssociationRequest.Builder()
.addDeviceFilter(classicBluetoothDeviceFilter)
.addDeviceFilter(leBluetoothDeviceFilter)
.setSingleDevice(false)
.build()
private val deviceManager: CompanionDeviceManager by lazy {
getSystemService(COMPANION_DEVICE_SERVICE) as CompanionDeviceManager
}
val mBluetoothAdapter: BluetoothAdapter by lazy {
val java = BluetoothManager::class.java
getSystemService(java)!!.adapter }
val executor: Executor = Executor { it.run() }
private val chooserLauncher =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
if (result.resultCode == RESULT_OK) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
val deviceToPair: BluetoothDevice? =
result.data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)
val isConnected = deviceToPair?.createBond()
Toast.makeText(this, "Connected: $isConnected", Toast.LENGTH_SHORT).show()
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU) {
val deviceToPair: BluetoothDevice? = result.data?.getParcelableExtra(
CompanionDeviceManager.EXTRA_DEVICE,
BluetoothDevice::class.java
)
val isConnected = deviceToPair?.createBond()
Toast.makeText(this, "Connected: $isConnected", Toast.LENGTH_SHORT).show()
}
} else {
Log.i("Hereeee2", "User cancelled device selection")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
checkAndRequestBluetoothPermissions()
findViewById(R.id.connect).setOnClickListener {
if(isBluetoothEnabled && isLocationServiceEnabled()){
findDevices()
} else {
Toast.makeText(this, "Please grant bluetooth permissions", Toast.LENGTH_SHORT).show()
}
}
findViewById(R.id.send).setOnClickListener {
if(isBluetoothEnabled && isLocationServiceEnabled()){
isClient = true
val pairedDevices = mBluetoothAdapter.bondedDevices
val device = pairedDevices.firstOrNull() // You can filter by name/MAC
if (device != null) {
ConnectThread(device).start()
} else {
Toast.makeText(this, "No paired devices found", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this, "Please grant bluetooth permissions and enable location ", Toast.LENGTH_SHORT).show()
}
}
findViewById(R.id.receive).setOnClickListener {
if(isBluetoothEnabled && isLocationServiceEnabled()){
isClient = false
AcceptThread().start()
} else {
Toast.makeText(this, "Please grant bluetooth permissions and enable location", Toast.LENGTH_SHORT).show()
}
}
}
private fun findDevices() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
deviceManager.associate(
pairingRequest,
executor,
object : CompanionDeviceManager.Callback() {
// Called when a device is found. Launch the IntentSender so the user
// can select the device they want to pair with.
override fun onAssociationPending(intentSender: IntentSender) {
chooserLauncher.launch(IntentSenderRequest.Builder(intentSender).build())
}
override fun onAssociationCreated(associationInfo: AssociationInfo) {
// An association is created.
Log.i("Hereeee3", associationInfo.toString())
val associationId = associationInfo.id
val macAddress = associationInfo.deviceMacAddress
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
val isConnected = associationInfo.associatedDevice?.bluetoothDevice?.createBond()
Toast.makeText(this@MainActivity, "Connected: $isConnected", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(errorMessage: CharSequence?) {
Log.i("Hereeee4", errorMessage.toString())
}
})
} else {
deviceManager.associate(
pairingRequest,
object : CompanionDeviceManager.Callback() {
// Called when a device is found. Launch the IntentSender so the user
// can select the device they want to pair with.
override fun onDeviceFound(intentSender: IntentSender) {
chooserLauncher.launch(IntentSenderRequest.Builder(intentSender).build())
}
override fun onFailure(error: CharSequence?) {
Log.i("Hereeee41", error.toString())
}
}, null
)
}
}
private val NAME = "MyBluetoothApp"
private val MY_UUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // SPP UUID
private inner class AcceptThread : Thread() {
private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) {
mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID)
}
var shouldLoop = true
override fun run() {
// Keep listening until exception occurs or a socket is returned.
while (shouldLoop) {
val socket: BluetoothSocket? = try {
mmServerSocket?.accept()
} catch (e: IOException) {
Log.e("Hereeee8", "Socket's accept() method failed", e)
shouldLoop = false
null
}
socket?.also {
manageMyConnectedSocket(it)
mmServerSocket?.close()
shouldLoop = false
}
}
}
fun cancel() {
try {
shouldLoop = false
mmServerSocket?.close()
} catch (e: IOException) {
Log.e("Hereeee9", "Could not close the server socket", e)
}
}
}
private inner class ConnectThread(device: BluetoothDevice) : Thread() {
private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) {
device.createRfcommSocketToServiceRecord(MY_UUID)
}
override fun run() {
mBluetoothAdapter.cancelDiscovery()
try {
mmSocket?.connect()
// Log.i("BluetoothClient", "Connected to ${device.name}")
mmSocket?.let { manageMyConnectedSocket(it) }
} catch (e: IOException) {
// Log.e("BluetoothClient", "Could not connect to ${device.name}", e)
try {
mmSocket?.close()
} catch (closeException: IOException) {
Log.e("Hereeee10", "Could not close client socket", closeException)
}
}
}
fun cancel() {
try {
mmSocket?.close()
} catch (e: IOException) {
Log.e("Hereeee11", "Could not close client socket", e)
}
}
}
private var connectedThread: MyBluetoothService.ConnectedThread? = null
private fun manageMyConnectedSocket(socket: BluetoothSocket) {
val bluetoothService = MyBluetoothService(handler)
connectedThread = bluetoothService.ConnectedThread(socket)
connectedThread?.start()
if (isClient) { //
when (msg.what) {
MESSAGE_READ -> {
val readBuf = msg.obj as ByteArray
val receivedMessage = String(readBuf, 0, msg.arg1)
Log.i("Hereeee12", "Received: $receivedMessage")
Toast.makeText(this, "Received: $receivedMessage", Toast.LENGTH_SHORT).show()
true
}
MESSAGE_WRITE -> {
Log.i("Hereeee13", "Data sent successfully")
true
}
MESSAGE_TOAST -> {
Toast.makeText(this, msg.data.getString("toast"), Toast.LENGTH_SHORT).show()
true
}
else -> false
}
}
companion object {
private const val TAG = "Hereeee22"
const val MESSAGE_READ = 0
const val MESSAGE_WRITE = 1
const val MESSAGE_TOAST = 2
}
private inner class MyBluetoothService(private val handler: Handler) {
inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() {
private val mmInStream: InputStream = mmSocket.inputStream
private val mmOutStream: OutputStream = mmSocket.outputStream
private val mmBuffer: ByteArray = ByteArray(1024)
override fun run() {
var numBytes: Int
while (true) {
numBytes = try {
mmInStream.read(mmBuffer)
} catch (e: IOException) {
Log.d(TAG, "Input stream was disconnected", e)
break
}
val readMsg = handler.obtainMessage(
MESSAGE_READ, numBytes, -1, mmBuffer.clone() // clone buffer
)
readMsg.sendToTarget()
}
}
fun write(bytes: ByteArray) {
try {
mmOutStream.write(bytes)
val writtenMsg = handler.obtainMessage(MESSAGE_WRITE, -1, -1, bytes)
writtenMsg.sendToTarget()
} catch (e: IOException) {
Log.e(TAG, "Error occurred when sending data", e)
val writeErrorMsg = handler.obtainMessage(MESSAGE_TOAST)
val bundle = Bundle().apply {
putString("toast", "Couldn't send data to the other device")
}
writeErrorMsg.data = bundle
handler.sendMessage(writeErrorMsg)
}
}
fun cancel() {
try {
mmSocket.close()
} catch (e: IOException) {
Log.e(TAG, "Could not close the connect socket", e)
}
}
}
fun startCommunication(socket: BluetoothSocket) {
ConnectedThread(socket).start()
}
}
}
Код: Выделить всё

Я также включил Bluetooth и определение местоположения на другом устройстве
Вот полный исходный код
Подробнее здесь: https://stackoverflow.com/questions/798 ... -my-device