onLeScan never gets called android

我是研究僧i 提交于 2019-12-10 23:44:32

问题


I have an app on an iPad that sends out Bluetooth LE information in place of its device name. I'm trying to capture that information in my Android code and update the UI in some way. Basically I need to scan for devices continuously and use the "device name" according to my protocol to update my Android UI. I know this isn't the right way to do things and I do plan to refactor both apps to correctly use Bluetooth LE, but I need this done soon and I don't have the time right now.

In my code below I know that scanLeDevices is getting called due to some Logs I put in, but the print statement I have in onLeScan is never getting called. Can anybody please tell me why? I've been stuck on this for a long time...

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
               }
           });
       }
    };
}

回答1:


I can't say for certain what's wrong, but here are a few ideas:

  1. test the return value of startLeScan(). If startLeScan() returns false, the scan didn't start, likely due to permissions problems. See http://developer.android.com/guide/topics/connectivity/bluetooth-le.html#permissions
  2. make SCAN_TIME longer. For example SCAN_TIME = 10000. If SCAN_TIME is shorter than the broadcast interval of your Beacon, your program might not detect it.
  3. remove the call to scanLeDevice() from onCreate(). As it is, when this program starts, onCreate() calls scanLeDevice(), then onResume() is called almost immediately, and calls scanLeDevice() again. I don't know what happens if you call startLeScan() when a scan is already running, but I think it would be good to avoid doing that.
  4. Reboot your Android device. I've found this to be helpful during BLE development, when my BLE app stops working.
  5. Test that another BLE detection app can see your BLE device.



回答2:


1.check permission first, like this(only need 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.if you use gradle, please check targetSdkVersion, when I set targetSdkVersion=24, onLeScan never called, but I change targetSdkVersion = 22, onLeScan get Called, I don't know why, it takes me hours to find this problem.




回答3:


You need BOTH permissions in your AndroidManifest.xml in oder to scan for devices:

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


来源:https://stackoverflow.com/questions/21515885/onlescan-never-gets-called-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!