onLeScan永远不会被称为android

duk*_*ke_ 2 android bluetooth bluetooth-lowenergy

我在iPad上有一个应用程序,它发送蓝牙LE信息代替其设备名称.我正试图在我的Android代码中捕获该信息并以某种方式更新UI.基本上我需要连续扫描设备并根据我的协议使用"设备名称"来更新我的Android UI.我知道这不是正确的做事方式,我确实计划重构两个应用程序以正确使用蓝牙LE,但我很快就需要这样做,我现在没有时间.

在下面的代码中,我知道scanLeDevices由于我放入的一些Logs而被调用,但是我在onLeScan中的print语句永远不会被调用.谁能告诉我为什么?我已经坚持了很久......

public class MainActivity extends Activity {
    private static final String TAG = "...";
    List<String> listItems=new ArrayList<String>();
    ArrayAdapter<String> adapter;

    BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    TextView mainView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_main);
        setProgressBarIndeterminate(true);

        mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        mainView = (TextView) findViewById(R.id.main_view);

        scanLeDevice(true);     
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            //Bluetooth is disabled
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivity(enableBtIntent);
            finish();
            return;
        }

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "No LE Support.", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

        scanLeDevice(true);
    }

    private static final long SCAN_TIME = 1000;
    boolean mScanning = false;
    private void scanLeDevice(final boolean enable) {
        Log.i(null, "Inside scanLeDevice");
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    Log.i(null, "Calling stopLeScan");
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                }
            }, SCAN_TIME);

            mScanning = true;
            Log.i(null, "Calling startLeScan");
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

    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(null, "INSIDE ONLESCAN");
                   //DO MY WORK
               }
           });
       }
    };
}
Run Code Online (Sandbox Code Playgroud)

小智 8

我不能肯定地说出了什么问题,但这里有一些想法:

  1. 测试startLeScan()的返回值.如果startLeScan()返回false,则扫描无法启动,可能是由于权限问题.请参阅http://developer.android.com/guide/topics/connectivity/bluetooth-le.html#permissions
  2. 使SCAN_TIME更长.例如,SCAN_TIME = 10000.如果SCAN_TIME短于Beacon的广播间隔,则程序可能无法检测到它.
  3. 从onCreate()中删除对scanLeDevice()的调用.实际上,当这个程序启动时,onCreate()调用scanLeDevice(),然后几乎立即调用onResume(),并再次调用scanLeDevice().我不知道如果你在扫描已经运行时调用startLeScan()会发生什么,但我认为避免这样做会很好.
  4. 重新启动您的Android设备.我发现这在BLE开发过程中很有用,当我的BLE应用程序停止工作时.
  5. 测试另一个BLE检测应用程序可以看到您的BLE设备.

  • 对于那些像我这样浪费时间的人,我将添加第六种情况:Android的较新API要求在扫描BLE时也必须打开位置服务。因此,也请检查一下。;) (2认同)