본문 바로가기

Study/Android

[Android] Android 12에서 강화된 블루투스 퍼미션

블루투스를 켜고 끄거나 통신을 하여 정보를 가져오고 보내주는 작업을 하려한다.

 

Android 개발자 문서에 나와있는대로 하였을 때 앱이 팅기면서 Security Exception을 터뜨리게 된다.

 

Manifest에 권한 부여하기


<manifest>
  <uses-permission android:name="android.permission.BLUETOOTH" />
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

  <!-- If your app targets Android 9 or lower, you can declare
       ACCESS_COARSE_LOCATION instead. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

</manifest>

 

Android 12 이상부터 블루투스 관련 Permission이 강화되었기 때문에 별도의 권한을 더 부여해야 한다.

 

<manifest>

    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30"
    />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30"
    />

    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />


</manifest>

 

 

화면 구성하기


우선은 다음과 같이 버튼 4개만 넣어두었고, 이 포스팅에서는 블루투스를 켜고 끄는 것까지만 구현할 것이다.

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    <Button
            android:id="@+id/btnBluetoothOn"
            android:text="블루투스 ON"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.128"
            app:layout_constraintVertical_bias="0.077"
    />
    <Button
            android:id="@+id/btnBluetoothOff"
            android:text="블루투스 OFF"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.418"
            app:layout_constraintVertical_bias="0.076"
    />
    <Button
            android:id="@+id/btnBluetoothSend"
            android:text="정보발신"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.128"
            app:layout_constraintVertical_bias="0.179"
    />
    <Button
            android:id="@+id/btnBluetoothReceive"
            android:text="정보수신"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.418"
            app:layout_constraintVertical_bias="0.178"
    />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

기능 구현하기


이제 블루투스 관련 모듈을 사용하기 위해 BluetoothAdapter를 사용할 것이며 블루투스 관련 변수를 1로 주어 전역에 설정해 둘 것이다

 

class MainActivity : AppCompatActivity() {
    private val requestEnableBt = 1
    private var bluetoothAdapter: BluetoothAdapter? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        bluetoothPermissionChecker()

        val bluetoothOnBtn = findViewById<Button>(R.id.btnBluetoothOn)
        val bluetoothOffBtn = findViewById<Button>(R.id.btnBluetoothOff)

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()

        bluetoothOnBtn.setOnClickListener { bluetoothOn() }
        bluetoothOffBtn.setOnClickListener { bluetoothOff() }
    }

 

우선 전역으로 requestEnableBt라는 변수를 1로 선언해주고, bluetoothAdapter를 null로 지정해둔다.

 

bluetoothPermissionChecker라는 함수를 가장 먼저 실행시켜서 Manifest에서 추가한 Permission을 부여해주도록 해야할 것이다.

 

그 다음 켜고 끄는 버튼을 ID값으로 가져온 다음 해당 버튼을 클릭할 때 함수가 작동되도록 할 것이다. 

 

퍼미션을 체크하는 함수는 다음과 같다.

 

private fun bluetoothPermissionChecker() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        requestPermissions(
            arrayOf(
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_ADVERTISE,
                Manifest.permission.BLUETOOTH_CONNECT
            ),
            requestEnableBt
        )
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        requestPermissions(
            arrayOf(
                Manifest.permission.BLUETOOTH
            ),
            requestEnableBt
        )
    }
}

 

버튼을 탭했을 때 블루투스를 켜고 끄는 함수는 다음과 같다.

 

private fun bluetoothOn() {
    if (bluetoothAdapter == null) {
        Toast.makeText(this, "블루투스를 지원하지 않는 기기입니다", Toast.LENGTH_LONG).show()
    } else {
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        startActivityForResult(enableBtIntent, requestEnableBt)
    }
}

private fun bluetoothOff() {
    bluetoothAdapter?.disable() ?: Toast.makeText(this, "블루투스를 지원하지 않는 기기입니다", Toast.LENGTH_LONG).show()
}

 

 

전체코드


package com.andapp.bluetooth

import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity


class MainActivity : AppCompatActivity() {
    private val requestEnableBt = 1
    private var bluetoothAdapter: BluetoothAdapter? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        bluetoothPermissionChecker()

        val bluetoothOnBtn = findViewById<Button>(R.id.btnBluetoothOn)
        val bluetoothOffBtn = findViewById<Button>(R.id.btnBluetoothOff)

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()

        if (bluetoothAdapter != null) {
            if (!bluetoothAdapter!!.isEnabled) {
                bluetoothOnBtn.isClickable = true
            } else {
                bluetoothOffBtn.isClickable = true
            }
        }

        bluetoothOnBtn.setOnClickListener { bluetoothOn() }
        bluetoothOffBtn.setOnClickListener { bluetoothOff() }
    }

    private fun bluetoothPermissionChecker() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            requestPermissions(
                arrayOf(
                    Manifest.permission.BLUETOOTH,
                    Manifest.permission.BLUETOOTH_SCAN,
                    Manifest.permission.BLUETOOTH_ADVERTISE,
                    Manifest.permission.BLUETOOTH_CONNECT
                ),
                requestEnableBt
            )
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(
                arrayOf(
                    Manifest.permission.BLUETOOTH
                ),
                requestEnableBt
            )
        }
    }

    private fun bluetoothOn() {
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "블루투스를 지원하지 않는 기기입니다", Toast.LENGTH_LONG).show()
        } else {
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableBtIntent, requestEnableBt)
        }
    }

    private fun bluetoothOff() {
        bluetoothAdapter?.disable() ?: Toast.makeText(this, "블루투스를 지원하지 않는 기기입니다", Toast.LENGTH_LONG).show()
    }
}

 

 

기기에 직접 입력한 값을 전달하거나 기기로부터 값을 받아오는 경우는 다음 포스팅에 이어서 소개할 것이다.

'Study > Android' 카테고리의 다른 글

[Android] 블루투스 개념  (2) 2022.07.17
Android : Google Maps, 구글 지도 사용하기  (0) 2022.02.16
Android : Camera  (0) 2022.02.16
Android : SQLite  (0) 2022.02.16
Android : 장면 전환 시 데이터 주고 받기  (0) 2022.02.16