素人のアンドロイドアプリ開発日記

BLE用のクラスを作ってみる

2018.02.25

BLEを使う時にラッパーしてくれるクラスを作りました。

使ってるやつ

public class BLEUtil {
    private BluetoothManager bluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private CallbackFunction callback;

    Handler handler;
    public BLEUtil(){
        handler = new Handler();
    }

    public static final int ERROR_ACTION_REQUEST_ENABLE = 261;
    public static final int ERROR_PERMISSION = 262;
    public static final int ERROR_DEVICE = 263;
    public static final int ERROR_NO_BLE = 264;



    public void setOnCallbackFunction(CallbackFunction _callback) {
        callback = _callback;
    }
    /*==
            条件判別
    == */
    public void init(Context _ctx){
        bluetoothManager = (BluetoothManager) _ctx.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        if (!_ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            callback.callError(ERROR_NO_BLE);
        }else if (!mBluetoothAdapter.isEnabled()) {
            callback.callError(ERROR_ACTION_REQUEST_ENABLE);
        }else if (ActivityCompat.checkSelfPermission(_ctx,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(_ctx, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            callback.callError(ERROR_PERMISSION);
        }else{
            _bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
            startscan();
        }
    }
    /*==
        スキャンをする
    == */
    private BluetoothLeScanner _bluetoothLeScanner;
    Boolean scanning = false;
    private int TIMEOUT = 0;

    public void setTIMEOUT(int _time){
        TIMEOUT = _time;
    }

    String address = "";

    //setMacAddress
    public void setMacAddress(String _address){
        address = Util.getAddressDot(_address);

    }
    Boolean oneshot = false;
    Boolean oneshotFlag = false;

    public void setOneShot(Boolean _oneshot){
        oneshot = _oneshot;
    }
    private void startscan(){
        if(oneshot) {
            oneshotFlag = true;
        }
        scanning = true;
        ArrayList scFlList = new ArrayList();

        if(!address.isEmpty()) {
            Util.callLog("SCAN:"+address);
            ScanFilter scanFilter = new ScanFilter.Builder().setDeviceAddress(address).build();
            scFlList.add(scanFilter);
        }
        ScanSettings.Builder scSetBldr = new ScanSettings.Builder();
        scSetBldr.setScanMode(android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY).build();
        ScanSettings scSettings = scSetBldr.build();
        _bluetoothLeScanner.startScan(scFlList, scSettings, mScanCallback);


        if(TIMEOUT != 0){
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(scanning) {
                        scanning = false;
                        _bluetoothLeScanner.stopScan(mScanCallback);
                        callback.callTimeOut();
                    }
                }
            },TIMEOUT);
        }
    }

    public void stopscan(){
        if(scanning) {
            scanning = false;
            _bluetoothLeScanner.stopScan(mScanCallback);
        }
    }


    ScanCallback mScanCallback = new ScanCallback(){
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            //String name = result.getDevice().getName();
            if(oneshot){
                if(!oneshotFlag){
                    return;
                }
                oneshotFlag = false;
            }
            callback.callResult(result.getDevice());
        }


        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            callback.callError(ERROR_DEVICE);
        }
    };

    public interface CallbackFunction {
        public void callResult(BluetoothDevice device);
        public void callError(int errorNUM);
        public void callTimeOut();
    }
}

で使う場合には次のようにする

private void startScan(){
    bleutil.setOnCallbackFunction(new BLEUtil.CallbackFunction() {
        @Override
        public void callResult(BluetoothDevice device) {
            Util.callLog(device.getAddress());
            bleutil.stopscan();
            //startBLEConnect(device);
        }

        @Override
        public void callError(int errorNUM) {
            Util.callLog("BLE_ERROR:"+errorNUM);
            if(errorNUM == BLEUtil.ERROR_ACTION_REQUEST_ENABLE){
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, bleutil.ERROR_ACTION_REQUEST_ENABLE);
            }else if(errorNUM == BLEUtil.ERROR_PERMISSION){
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,}, bleutil.ERROR_PERMISSION);
            }else if(errorNUM == BLEUtil.ERROR_DEVICE){
                //コネクトに際してのエラー。端末のBLEが暴走の可能性

            }else if(errorNUM == BLEUtil.ERROR_NO_BLE){
                //この端末ではBLEが利用できません。
            }
        }
        @Override
        public void callTimeOut() {
            

        }
    });
    bleutil.setMacAddress(macaddress);
    bleutil.setOneShot(true);
    bleutil.setTIMEOUT(3000);
    bleutil.init(getApplicationContext());
}

権限の取得からの戻りは次のようにする

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == BLEUtil.ERROR_ACTION_REQUEST_ENABLE){
        if(resultCode == RESULT_OK){
            startScan();
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

@Override
public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
    switch (requestCode) {
        case BLEUtil.ERROR_PERMISSION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startScan();
            } else {
                Util.callLog("NG");
                finish();
            }
            return;
        }
    }
}

権限の追加もわすれずに

同じカテゴリの記事を紹介します

アプリ制作テンプレート回転し続けるには

カテゴリー:制作補助クラス

公開中のアプリ、是非ダウンロードしてみてください

2chまとめのたね

RSSを利用してさまざまなブログの情報をキュレーションしてくれるアプリ

インストールする

ひらがな戦記

OPENGL ES2 を利用したカルタのソーシャルゲーム

インストールする