안드로이드 6.0 마시멜로에서 변경된 중요 사항 중 블루투스, WiFi 권한 관련


블루투스 관련 앱이 정상적으로 검색과 연결이 잘 되던 것이 안드로이드 버전 6.0의 기기에서는 검색해 내지를 못하는 경험이 있을 것이다.

이것은 6.0에서의 정책상의 변화로 인해 발생하는 문제이다.

6.0에서 블루투스가 정상적으로 동작하기 위해서는 아래 권한이 Manifest에 선언되어 있으야만 한다.


ACCESS_FINE_LOCATION 혹은 ACCESS_COARSE_LOCATION 권한이 없으면 주변 WiFi / Bluetooth 디바이스를 발견할 수 없다.


위의 권한이 선언되어 있지 않으면 다음과 같은 메서드가 정상적으로 동작하지 않는다.


WifiManager.getScanResults()

BluetoothDevice.ACTION_FOUND

BluetoothLeScanner.startScan()

...


아래는 구글 안드로이드 API Reference 문서에서 소개하고 있는 내용이다.


Access to Hardware Identifier


To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.

To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:

Note: When a device running Android 6.0 (API level 23) initiates a background Wi-Fi or Bluetooth scan, the operation is visible to external devices as originating from a randomized MAC address.


https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html





BluetoothAdapter 클래스의 enable()라는 메소드를 통해서 Bluetooth를 강제적으로 활성화 할수 있으나

사용자로 하여금 선택할 수 있도록 하는 것이 더 바람직하다.


Google의 Android API Reference에서도 public boolean enable () 메소드에 대한 설명 가운데는

다음과 같이 사용자의 명백한 행동 없이

강제적으로 Bluetooth를 활성화시키지 말라고 얘기하고 있다.


Turn on the local Bluetooth adapter—do not use without explicit user action to turn on Bluetooth.


이때 Bluetooth를 활성화 하는 방법으로 Intent를 통해서 안드로이드 시스템에게 요청해서 

안드로이드 시스템이 사용자에게 다이얼로그 창을 띄워서 사용자가 선택하게 하고

사용자가 Bluetooth를 활성화하도록 선택을 하면 안드로이드 시스템이 Bluetooth를 

활성화 시키도록 하는 방법이 있다.

이때 BluetoothAdapter.ACTION_REQUEST_ENABLE라는 action을 Intent를 통해서

안드로이드 시스템에게 요청을 하면 된다.


Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivity(enableBtIntent)라고 해도 되나 사용자가 어떤 선택을 했느냐에 따라서

그에 맞는 어떤 행동을 해야할 필요가 있기때문에 startActivityForResult()를 사용했다.

사용자의 선택 여부를 통보받는 곳이 protected void onActivityResult() 메소드를 통해서이다.


ENABLE_BT가 전역변수를 다음과 같이 선언되어 있다고 할 때

private static final int ENABLE_BT = 1;


아래는 안드로이드 시스템에게 Bluetooth 활성화 여부를 사용자에게 묻고

그 결과에 따라 활성화를 하도록 하는 코드이다.


startActivityForResult(enableBtIntent, ENABLE_BT);


사용자의 선택결과를 통보 받기 위해서는 onActivityResult()를 이용하면 된다.


@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data){

if (requestCode == ENABLE_BT  

&& resultCode == Activity.RESULT_CANCELED){

Toast.makeText(this, "취소 했습니다", 1).show();

                finish();

} else if (requestCode == ENABLE_BT 

&& resultCode == Activity.RESULT_OK){

Toast.makeText(this, "블루투스를 활성화합니다.", 1).show();

  }

}



+ Recent posts