onLeScan永远不会被称为android

时间:2014-02-02 20:36:00

标签: 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
               }
           });
       }
    };
}

3 个答案:

答案 0 :(得分:6)

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

  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设备。

答案 1 :(得分:2)

您需要在AndroidManifest.xml中拥有BOTH权限才能扫描设备:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

答案 2 :(得分:2)

1.首先检查权限,像这样(只需要ACCESS_COARSE_LOCATION):

 private void checkPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;

    String[] permissions = new String[]{
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE};

    if (checkSelfPermission(permissions[0]) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(permissions, REQUEST_ENABLE_LOCATION);
    }
}

2.如果您使用gradle,请检查targetSdkVersion,当我设置targetSdkVersion = 24时,onLeScan从未调用过,但我更改了targetSdkVersion = 22, onLeScan得到了调用,我不知道为什么,这需要几个小时才能找到这个问题。