简体   繁体   English

首次单击扫描按钮后,应用程序崩溃,但重新打开后该应用程序可以工作

[英]App crashes after clicking scan button for the first time but the app works after i reopen it

I'm trying to create an indoor location services app in android studio.There is a scan button which start the discovery of BLE devices. 我正在尝试在android studio中创建一个室内定位服务应用程序。有一个扫描按钮可以开始发现BLE设备。 When i click on the scan button,the app crashes. 当我单击扫描按钮时,应用程序崩溃。 But when i reopen the app and click on the scan button again,it works. 但是,当我重新打开应用程序并再次单击扫描按钮时,它可以工作。

i tried this taken from one of the projects from stackoverflow. 我尝试了这从stackoverflow的项目之一。

Class variable: 类变量:

private BluetoothAdapter mBtAdapter = null;

final BluetoothManager btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBtAdapter = btManager.getAdapter();

if (mBtAdapter == null || !mBtAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}

public void onScanButton(){
    if (mBtAdapter.isEnabled()){
        scanLeDevice(true);
    }
}

this is my code 这是我的代码

    BluetoothManager btManager; //field 'btManager' is never used
    private BluetoothAdapter btAdapter = null;
    BluetoothLeScanner btScanner;
    Button startScanningButton;
    Button stopScanningButton;
    TextView peripheralTextView;
    private final static int REQUEST_ENABLE_BT = 1;
    private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        peripheralTextView = (TextView) findViewById(R.id.peripheralTextView);
        peripheralTextView.setMovementMethod(new ScrollingMovementMethod());

        startScanningButton = (Button) findViewById(R.id.StartScanButton);
        startScanningButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                startScanning();
            }
        });

        stopScanningButton = (Button) findViewById(R.id.StopScanButton);
        stopScanningButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                stopScanning();
            }
        });
        stopScanningButton.setVisibility(View.INVISIBLE);

        final BluetoothManager btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        btAdapter = btManager.getAdapter();
        btScanner = btAdapter.getBluetoothLeScanner();

        if (btAdapter != null && !btAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
        }

        // Make sure we have access coarse location enabled, if not, prompt the user to enable it
        if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("This app needs location access");
            builder.setMessage("Please grant location access so this app can detect peripherals.");
            builder.setPositiveButton(android.R.string.ok, null);
            builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
                }
            });
            builder.show();
        }
    }

    // Device scan callback.
    private ScanCallback leScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            peripheralTextView.append("MAC address: " + result.getDevice().getAddress() + " rssi: " + result.getRssi() + "TxPower:" + result.getTxPower() + "\n");

            // auto scroll for text view
            final int scrollAmount = peripheralTextView.getLayout().getLineTop(peripheralTextView.getLineCount()) - peripheralTextView.getHeight();
            // if there is no need to scroll, scrollAmount will be <=0
            if (scrollAmount > 0)
                peripheralTextView.scrollTo(0, scrollAmount);
        }
    };

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_COARSE_LOCATION: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    System.out.println("coarse location permission granted");
                } else {
                    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("Functionality limited");
                    builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
                    builder.setPositiveButton(android.R.string.ok, null);
                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                        @Override
                        public void onDismiss(DialogInterface dialog) {
                        }

                    });
                    builder.show();
                }
            }
        }
    }

    public void startScanning() {
        System.out.println("start scanning");
        peripheralTextView.setText("");
        startScanningButton.setVisibility(View.INVISIBLE);
        stopScanningButton.setVisibility(View.VISIBLE);
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                btScanner.startScan(leScanCallback);
            }
        });
    }

    public void stopScanning() {
        System.out.println("stopping scanning");
        peripheralTextView.append("Stopped Scanning");
        startScanningButton.setVisibility(View.VISIBLE);
        stopScanningButton.setVisibility(View.INVISIBLE);
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                btScanner.stopScan(leScanCallback);
            }
        });
    }
}

The logcat shows java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.le.BluetoothLeScanner.startScan(android.bluetooth.le.ScanCallback)' on a null object reference Logcat显示java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'void android.bluetooth.le.BluetoothLeScanner.startScan(android.bluetooth.le.ScanCallback)'

at com.example.myapplication.MainActivity$6.run(MainActivity.java:137) 在com.example.myapplication.MainActivity $ 6.run(MainActivity.java:137)

at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 在android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:245)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:641)

at java.lang.Thread.run(Thread.java:764) 在java.lang.Thread.run(Thread.java:764)

Before i click the Scan button,a prompt will be display asking to turn on the bluetooth.So bluetooth will be turned on 在我单击“扫描”按钮之前,将显示一个提示,要求您打开蓝牙。因此将打开蓝牙

You are wrong about that part. 您在那部分上错了。 You ask the user to enable it, but it might not have happened yet. 您要求用户启用它,但可能尚未发生。 At least you need to get the Scanner later on. 至少您以后需要安装扫描仪。

Currently you set the Scanner reference before the permission requesting has been initiated. 当前,在启动权限请求之前,您已设置扫描程序参考。

This also explains why it works after your App has crashed for the first time, because the 2nd time you come here the Permission has been enabled. 这也解释了为什么它在您的应用程序首次崩溃后仍然有效,因为您第二次来到这里时,权限已启用。


From the Javadoc of BluetoothAdapter#getBluetoothLeScanner() : BluetoothAdapter#getBluetoothLeScanner()的Javadoc中:

Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not supported on this device. 如果蓝牙已关闭或此设备不支持蓝牙LE广告,则将返回null。


You can change your code to: 您可以将代码更改为:

    public void startScanning() {

        btScanner = btAdapter.getBluetoothLeScanner();
        if (btScanner == null) {
            // not enabled yet or not supported
            return;
        }

        System.out.println("start scanning");
        peripheralTextView.setText("");
        startScanningButton.setVisibility(View.INVISIBLE);
        stopScanningButton.setVisibility(View.VISIBLE);
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                btScanner.startScan(leScanCallback);
            }
        });
    }

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

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