简体   繁体   English

在android studio中扫描ble模块(蓝牙4.0)

[英]Scan for ble module (bluetooth 4.0) in android studio

I'm trying to develop an app to scan for a BLE device. 我正在尝试开发一个应用来扫描BLE设备。 However, it only scans one time. 但是,它只扫描一次。 I tried to use a while loop to loop it but it hangs there. 我尝试使用while循环来循环它但它挂在那里。 The scanning part is at the proceed function: 扫描部分处于继续功能:

package com.example.user.myfriend;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;


public class MainActivity extends ActionBarActivity {
BluetoothAdapter mBluetoothAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {


    BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    hello();

}

public void hello() {

    if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
        Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

        startActivityForResult(enableBluetooth, 1);


    }
    proceed();
}


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

    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
            proceed();


        }

    }
    super.onActivityResult(requestCode, resultCode, data);
}

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {


    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {

        int startByte = 2;
        boolean patternFound = false;
        while (startByte <= 5) {

            if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
                    ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { //Identifies correct data length
                patternFound = true;
                break;
            }
            startByte++;
        }

        if (patternFound) {

            //Convert to hex String
            byte[] uuidBytes = new byte[16];
            System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
            String hexString = bytesToHex(uuidBytes);

            //Here is your UUID
            String uuid = hexString.substring(0, 8) + "-" +
                    hexString.substring(8, 12) + "-" +
                    hexString.substring(12, 16) + "-" +
                    hexString.substring(16, 20) + "-" +
                    hexString.substring(20, 32);

            //Here is your Major value
            int major = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);

            //Here is your Minor value
            int minor = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);

            if (major == 1) {
                RelativeLayout hai = (RelativeLayout) findViewById(R.id.hai);
                hai.setBackgroundColor(Color.YELLOW);

            }
            if (major == 2) {
                RelativeLayout hai = (RelativeLayout) findViewById(R.id.hai);
                hai.setBackgroundColor(Color.RED);

            }


        }


    }


};


private static String bytesToHex(byte[] bytes) {
    final char[] hexArray = "0123456789ABCDEF".toCharArray();
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

public void proceed() {
    boolean scanning = true;

    mBluetoothAdapter.startLeScan(mLeScanCallback);


    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        //  @Override
        public void run() {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);


        }
    }, 50000000);

}

} }

How can I make the app scan in a loop? 如何让应用程序循环扫描?

If "by scan in a loop?" 如果“通过循环扫描?” you mean detect all nearby broadcasting devices, you have done it. 你的意思是检测所有附近的广播设备,你已经完成了。 The line of code: 代码行:

mBluetoothAdapter.startLeScan(mLeScanCallback) 

causes scanning to begin. 导致扫描开始。 During scanning, the callback "mLeScanCallback" will be called as each broadcasting device is discovered. 在扫描期间,将在发现每个广播设备时调用回调“mLeScanCallback”。 The scan will remain in effect until 扫描将一直有效,直到

mBluetoothAdapter.stopScan(mLeScanCallback) 

is called. 叫做。 In your case, this will get called after a very long time: 50000000 milliseconds. 在你的情况下,这将在很长一段时间后被调用:50000000毫秒。

Perhaps you only have 1 broadcasting device in the area so you only get 1 callback when you test. 也许您在该区域只有1个广播设备,因此您在测试时只能获得1个回调。

Unfortunately it is highly probable that the model of the device that you're testing your app on behaves badly in terms of scan performance. 不幸的是,您测试应用程序的设备模型极有可能在扫描性能方面表现不佳。 It is because of this bug: 正是因为这个bug:

https://code.google.com/p/android/issues/detail?id=65863 https://code.google.com/p/android/issues/detail?id=65863

The exact nature of the problem is unknown but according to most of the participants of the issue aforementioned it is up to the Bluetooth Chipset mounted into Android device. 问题的确切性质是未知的,但根据上述问题的大多数参与者,这取决于安装在Android设备中的蓝牙芯片组。

The funny thing is that some devices handle the bluetooth performing it in loop instantly and some perform scan only once or several times. 有趣的是,有些设备会立即处理蓝牙执行循环,有些设备只执行一次或多次扫描。

I deal with BLE in Android on daily basis and the way I approached the problem was creation of the Object encapsulating periodic forcing Bluetooth scan. 我每天都在处理Android中的BLE,而我解决问题的方法是创建Object封装周期性强制蓝牙扫描。 My scheduler encapsulates single thread in which the instance of the LeScanCallback is started and stopped every n hundred milliseconds. 我的调度程序封装了单个线程,其中LeScanCallback的实例每隔n百毫秒启动和停止。 While it is a hack, it resolves the problem but starting from Android KitKat (BLE was introduced in API 18). 虽然它是一个黑客,它解决了问题,但从Android KitKat开始(BLE在API 18中引入)。

Of course using periodic force scan scheduler is optional in my library because of the fact that some Android devices don't need it to be working. 当然,在我的库中使用周期性强制扫描调度程序是可选的,因为某些Android设备不需要它工作。

Btw., sooner or later you will experience the system crash on Android JELLY_BEAN_MR2 resulting in displaying dialog that something went wrong. 顺便说一句,你迟早会在Android JELLY_BEAN_MR2上遇到系统崩溃,导致显示出错的对话框。

I suggest trying out the kontakt.io iBeacon library: documentation and howto can be found here: http://devdocs.kontakt.io . 我建议尝试kontakt.io iBeacon库:文档和howto可以在这里找到: http ://devdocs.kontakt.io。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM