Skip to content

Commit

Permalink
Create 0310.md
Browse files Browse the repository at this point in the history
summary for 0310
  • Loading branch information
magiccaller authored Mar 10, 2017
1 parent dfe74fa commit 5715808
Showing 1 changed file with 378 additions and 0 deletions.
378 changes: 378 additions & 0 deletions Programming/basicStudy/0310.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
#03_10

##BLE
- manifest 퍼미션
```java
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<--런타임 퍼미션 처리 해줄 것 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<---->

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

```
- Permission Control

```java
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import android.widget.Toast;

/**
* 1. 권한처리를 담당하는 클래스
* 권한변경시 PERMISSION_ARRAY의 값만 변경해주면 된다
*
* 2. Activity 에서 사용하기
* public class Activity implements PermissionControl.Callback{
* @Override
* protected void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState);
* setContentView(R.layout.activity_main);
* // 권한체크 호출
* PermissionControl.checkPermission(this);
* }
*
* @Override
* public Activity getActivity(){
* return this;
* }
* @Override
* public void init(){
* // 초기화 로직
* }
*
* @Override
* public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
* super.onRequestPermissionsResult(requestCode, permissions, grantResults);
* // 결과처리
* PermissionControl.onCheckResult(requestCode,grantResults);
* }
* }
*/

public class PermissionControl {
// 권한요청코드
private static final int REQ_PERMISSION = 9760345;
private static Callback callback = null;

// 요청할 권한 목록
public static final String PERMISSION_ARRAY[] = {
Manifest.permission.ACCESS_COARSE_LOCATION
, Manifest.permission.ACCESS_FINE_LOCATION
};

// 권한체크 함수
@TargetApi(Build.VERSION_CODES.M)
public static void checkPermission(Callback object){
callback = object;
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
Activity activity = callback.getActivity();
// 1.1 런타임 권한체크
// 위에 설정한 권한을 반복문을 돌면서 처리한다...
boolean permCheck = true;
for (String perm : PERMISSION_ARRAY) {
if (activity.checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
permCheck = false;
break;
}
}
// 1.2 퍼미션이 모두 true 이면 그냥 프로그램 실행
if (permCheck) {
callback.init();
} else {
activity.requestPermissions(PERMISSION_ARRAY, REQ_PERMISSION);
}
}else {
callback.init();
}
}

// 권한체크 후 콜백처리
public static void onCheckResult(int requestCode, int[] grantResults) {
boolean checkResult = true;
if(requestCode == REQ_PERMISSION) {
// 권한처리 결과값을 반복문을 돌면서 확인한 후 하나라도 승인되지 않았다면 false를 리턴해준다
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
checkResult = false;
break;
}
}
if(callback != null) {
if (checkResult) {
callback.init();
} else {
Toast.makeText(callback.getActivity(), "권한을 허용하지 않으시면 프로그램을 실행할 수 없습니다.", Toast.LENGTH_LONG).show();
}
callback = null;
}
}
}

interface Callback {
public Activity getActivity();
public void init();
}
}

```


- Main

```java

import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

@TargetApi(21)
public class MainActivity extends AppCompatActivity implements PermissionControl.Callback{
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE Not Supported",
Toast.LENGTH_SHORT).show();
finish();
}
// 1. 매니저로 아답터를 가져온다.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

}

@Override
protected void onResume() {
super.onResume();
PermissionControl.checkPermission(this);
}

@Override
public Activity getActivity() {
return this;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionControl.onCheckResult(requestCode,grantResults);
}

// PermissionControl 에서 호출하는 초기화 함수
// 상단에서 Permission Control 의 인터페이스를 implements 해야 한다
@Override
public void init(){
// 2. 아답터를 사용할 수 없으면 BluetoothAdapter.ACTION_REQUEST_ENABLE 호출
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
// 3. 아답터를 사용할 수 있으면 버전 체크를 해서 21 이상이면
if (Build.VERSION.SDK_INT >= 21) {
// 3.1 getBluetoothLeScanner() 사용
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<ScanFilter>();
}
scanLeDevice(true);
}
}
@Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}

@Override
protected void onDestroy() {
if (mGatt != null) {
mGatt.close();
mGatt = null;
}
super.onDestroy();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
//Bluetooth not enabled.
finish();
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}

// 4. 블루투스 스캔 시작
private void scanLeDevice(final boolean enable) {

// 4.1 스캔시작
if (enable) {

// 4.1.2 10초후에 스캔을 종료하는 sub thread 동작
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);

// 4.1.1 스캔 시작
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}

// 4.2 스캔 종료
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}

// 5. 스캔이 종료된 후에 호출된다
private ScanCallback mScanCallback = new ScanCallback() {

// 5.1 블루투스 기기가 하나 검색될경우
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}

// 5.2 목록
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}

@Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};

private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};

// 6. 검색 후 디바이스 연결
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
// 6.1 디바이스 커넥션시 gattCallback 을 담아서 연결
mGatt = device.connectGatt(this, false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}

// 7. 디바이스 연결후 호출되는 콜백
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}

}

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
Log.i("onServicesDiscovered", services.toString());
gatt.readCharacteristic(services.get(1).getCharacteristics().get
(0));
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
gatt.disconnect();
}
};


}
```

0 comments on commit 5715808

Please sign in to comment.