반응형

2017. 3. 20

Android API 23 (Marshmallow) 이후 버전에서 Bluetooth LE 관련 코드가 동작하려면 다음 두 퍼미션중 하나를  AndroidManifest.xml파일에 추가해야 합니다. 여기서는 퍼미션과 관련된 내용만 있습니다. 나머지 내용은 본 포스팅에서 2016. 6.4일 작성된 부분을 보세요..

1
2
android.permission.ACCESS_COARSE_LOCATION
android.permission.ACCESS_FINE_LOCATION
cs


추가 안하면 다음과 같은 에러가 납니다.

1
java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
cs



AndroidManifest.xml파일에 android.permission.ACCESS_COARSE_LOCATION 퍼미션을 추가한 후..

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tistory.webnautes.bluetoothble">
 
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
    <uses-feature
        android:name="android.hardware.bluetooth_le"
        android:required="true" />
cs


 MainActivity.java에  Runtime Permission관련 코드 추가해야 합니다. 우선 다음 코드들을 추가해 준 후..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  static final int PERMISSION_REQUEST_CODE = 1;
    String[] PERMISSIONS  = {"android.permission.ACCESS_COARSE_LOCATION"};
 
    private boolean hasPermissions(String[] permissions) {
        int ret = 0;
        //스트링 배열에 있는 퍼미션들의 허가 상태 여부 확인
        for (String perms : permissions){
            ret = checkCallingOrSelfPermission(perms);
            if (!(ret == PackageManager.PERMISSION_GRANTED)){
                //퍼미션 허가 안된 경우
                return false;
            }
        }
       
        //모든 퍼미션이 허가된 경우
        return true;
    }
 
    private void requestNecessaryPermissions(String[] permissions) {
        //마시멜로( API 23 )이상에서 런타임 퍼미션(Runtime Permission) 요청
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissions, PERMISSION_REQUEST_CODE);
        }
    }
 
    @Override
    public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
        switch(permsRequestCode){
 
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0) {
                    boolean Accepted = grantResults[0== PackageManager.PERMISSION_GRANTED;
 
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 
                        if (!Accepted  )
                        {
                            showDialogforPermission("앱을 실행하려면 퍼미션을 허가하셔야합니다.");
                            return;
                        }else
                        {
                            //이미 사용자에게 퍼미션 허가를 받음.
                        }
                    }
                }
                break;
        }
    }
 
    private void showDialogforPermission(String msg) {
 
        final AlertDialog.Builder myDialog = new AlertDialog.Builder( MainActivity.this);
        myDialog.setTitle("알림");
        myDialog.setMessage(msg);
        myDialog.setCancelable(false);
        myDialog.setPositiveButton("예"new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    requestPermissions(PERMISSIONS, PERMISSION_REQUEST_CODE);
                }
 
            }
        });
        myDialog.setNegativeButton("아니오"new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                finish();
            }
        });
        myDialog.show();
    }
cs


MainActivity의 onCreate 메소드에서 블루투스 관련 코드가 시작되기 전에 넣어줘야 합니다.

1
2
3
4
5
       if (!hasPermissions(PERMISSIONS)) { //퍼미션 허가를 했었는지 여부를 확인
            requestNecessaryPermissions(PERMISSIONS);//퍼미션 허가안되어 있다면 사용자에게 요청
        } else {
            //이미 사용자에게 퍼미션 허가를 받음.
        }
cs



전체 프로젝트 파일을 이곳에 올려둡니다.

BluetoothBLE.z01

BluetoothBLE.zip



2016. 6. 4

안드로이드 폰에서 Bluetooth BLE를 사용하는 Arduino 101를 검색하고 제공하는 서비스의  특정 Characteristic에 값을 기록하거나 읽어오는 것을 해봤습니다.  아래 링크에 있는 안드로이드 코드의 일부를 수정하여 사용했습니다.

https://github.com/youten/BLERW



수정한 부분은 DeviceActivity의 코드에서 아두이노 101에서 제공하는 서비스와 Characteristic를 지정해 주어 동작이 잘되도록 한 것과 일부 UI입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    @Override
    public void onClick(View v) {
        Toast.makeText(getApplicationContext(), "value=",  Toast.LENGTH_LONG);
 
        if (v.getId() == R.id.read_state) {
 
            BluetoothGattService disService = mConnGatt.getService(UUID.fromString("19B10000-E8F2-537E-4F6C-D104768A1214"));
            if (disService == null) {
                Log.d("""Dis service not found!");
                return;
            }
 
 
            BluetoothGattCharacteristic characteristic = disService.getCharacteristic(UUID.fromString("19B10001-E8F2-537E-4F6C-D104768A1214"));
 
            if (characteristic == null) {
                Log.d(""" charateristic not found!");
                return;
            }
 
            boolean result = mConnGatt.readCharacteristic(characteristic);
            if (result == false) {
                Log.d("""reading is failed!");
            }
 
 
 
        } else if (v.getId() == R.id.turn_off_led) {
            BluetoothGattService disService = mConnGatt.getService(UUID.fromString("19B10000-E8F2-537E-4F6C-D104768A1214"));
            if (disService == null) {
                Log.d("""Dis service not found!");
                return;
            }
 
 
            BluetoothGattCharacteristic characteristic = disService.getCharacteristic(UUID.fromString("19B10001-E8F2-537E-4F6C-D104768A1214"));
 
            if (characteristic == null) {
                Log.d("""firmware revison charateristic not found!");
                return;
            }
 
 
            characteristic.setValue(new byte[] { (byte0x00 });
                if (mConnGatt.writeCharacteristic(characteristic)) {
 
                }
 
 
        } else if (v.getId() == R.id.turn_on_led) {
 
            BluetoothGattService disService = mConnGatt.getService(UUID.fromString("19B10000-E8F2-537E-4F6C-D104768A1214"));
            if (disService == null) {
                Log.d("""Dis service not found!");
                return;
            }
 
 
            BluetoothGattCharacteristic characteristic = disService.getCharacteristic(UUID.fromString("19B10001-E8F2-537E-4F6C-D104768A1214"));
 
            if (characteristic == null) {
                Log.d("""charateristic not found!");
                return;
            }
 
 
 
            characteristic.setValue(new byte[] { (byte0x01 });
                if (mConnGatt.writeCharacteristic(characteristic)) {
 
                }
 
        }
    }

cs


 

진행하기 전에 아두이노 101에 LED 예제가 업로드 되어 있어야 합니다. 메뉴에서 파일 - 예제 -  CurieBLE - LED를 선택합니다. 

코드 상단에 Arduino 101에서 제공하는 LED 서비스의 UUID와 LED를 제어에 사용되는 Characteristic의 UUID를 볼 수 있습니다.

1
2
3
4
5
6
7
#include <CurieBLE.h>
 
BLEPeripheral blePeripheral;  // BLE Peripheral Device (the board you're programming)
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
 
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEUnsignedCharCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
cs


아두이노 101이 Bluetooth LE 장치로 검색되어 질때 노출되는 문자열을 LED로 지정하고 있습니다.

1
2
3
  // set advertised local name and service UUID:
  blePeripheral.setLocalName("LED");
  blePeripheral.setAdvertisedServiceUuid(ledService.uuid());
cs


안드로이드 앱을 실행시킨 후.. SCAN 버튼을  눌러주면  BLE장치의 이름, 맥어드레스 그리고 RSSI값을 출력해줍니다.  이때 STOP 버튼을 눌러주면 스캔이 중단됩니다.  첫번째 줄에 있는 LED 장치가 아두이노 101입니다. 선택해주면..




다른 화면이 보이는데 이때  READ_STATE버튼을 클릭하면 현재 LED의 상태값을 읽어와  화면에 출력해줍니다. 





TURN ON LED버튼을 클릭하면 아두이노 101에 연결된 LED가 켜지고 이때 다시 READ_STATE 버튼을 클릭해보면 1로 값이 변경된 것을 확인할 수 있습니다. 





다시 TURN OFF LED를 클릭하여 LED를 끄고 다시 READ_STATE버튼을 클릭해보면 상태값이 0으로 변한 것을 확인 할 수 있습니다ㅏ. 




반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts