BLE应用程序崩溃,当应用程序检查蓝牙是否enablea和mBluetoothAdapter.isMultipleAdvertisementSupported()返回false

问题描述:

我希望有人可以给我一个关于这个问题的建议。我一直试图解决它没有任何运气,我也看到这是一个真正的问题,并有很多讨论。BLE应用程序崩溃,当应用程序检查蓝牙是否enablea和mBluetoothAdapter.isMultipleAdvertisementSupported()返回false

这是一个简单的应用程序,只有一个按钮。该按钮将使设备在按下时作为信标工作,并且释放按钮时它将停止发送数据。开始时,应用程序将检查此question中建议的蓝牙和BLE是否受支持。

当设备没有打开蓝牙并要求用户将其打开时,应用程序崩溃。但是,当设备启用蓝牙时,它不会崩溃。

做了进一步的分析,我看到下面的代码片段被执行,向我显示消息,该设备不支持BLE。

if (mBluetoothAdapter.isEnabled()==false) { 
    mBluetoothAdapter.enable(); 
    Toast.makeText(getApplicationContext(),"Enabling Bluetooth", Toast.LENGTH_SHORT).show(); 
    Log.e("BLE_code", "State: " + mBluetoothAdapter.getState()); 
} 

if(!mBluetoothAdapter.isMultipleAdvertisementSupported()){ 
    Toast.makeText(getApplicationContext(),"Device does not support BLE", Toast.LENGTH_SHORT).show(); 
} 

我也搜索过此website,看看如果设备不支持BLE,它可能不会有(我用三星Galaxy S7工作),但我已经试过了,建议应用检查设备是否允许在外设模式下使用BLE,并且可以发现它。 (在谷歌商店有很多应用程序作为信标工作)。

还有更多的人在同一问题here,here和其他一些问题上挣扎。它可能有点旧,但仍然有效。

你可以在下面找到完整的代码来测试。

EDITED:

MainActivity.java

package com.ble_app.aecheverri.ble_app; 
import android.bluetooth.le.AdvertiseSettings; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Handler; 
import android.support.annotation.RequiresApi; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.MotionEvent; 
import android.view.View; 
import android.widget.Button; 
import android.widget.Toast; 
import android.content.Intent; 
import android.util.Log; 
import java.nio.charset.Charset; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothManager; 
import android.bluetooth.le.BluetoothLeAdvertiser; 
import android.os.ParcelUuid; 
import android.bluetooth.le.AdvertiseData; 
import android.bluetooth.le.AdvertiseCallback; 
import android.widget.EditText; 
import java.util.UUID; 
import android.content.Context; 


public class MainActivity extends AppCompatActivity { 

    private BluetoothAdapter mBluetoothAdapter; 
    private final static int REQUEST_ENABLE_BT = 1; 
    private Button btn; 
    private BluetoothLeAdvertiser mBluetoothLeAdvertiser; 

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Button btn = (Button) findViewById(R.id.BLE_CHECK_button); 
     final EditText edit = (EditText) findViewById(R.id.Data_Sent); 
     final BluetoothManager bluetoothManager = 
       (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 
     mBluetoothAdapter = bluetoothManager.getAdapter(); 
     mBluetoothAdapter.setName("APEX"); 

     //Check if bluetooth is on, otherwise, turn it on! 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); 

     Log.e("BLE_code", "State: " + mBluetoothAdapter.getBluetoothLeAdvertiser()); 

     //getBluetoothLeScanner 
     if (mBluetoothAdapter.isEnabled()==false) { 
      mBluetoothAdapter.enable(); 
      Toast.makeText(getApplicationContext(),"Enabling Bluetooth", Toast.LENGTH_SHORT).show(); 
      Log.e("BLE_code", "State: " + mBluetoothAdapter.getState()); 
     } 

     if(!mBluetoothAdapter.isMultipleAdvertisementSupported()){ 
      Toast.makeText(getApplicationContext(),"Device does not support BLE", Toast.LENGTH_SHORT).show(); 
     } 


     final BluetoothLeAdvertiser advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser(); 
     //Set the advertise settings and the power of the signal 
     final AdvertiseSettings settings = new AdvertiseSettings.Builder() 
       .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) 
       .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) 
       .setConnectable(false) 
       .build(); 


     final AdvertiseCallback advertisingCallback = new AdvertiseCallback() { 
      @Override 
      public void onStartSuccess(AdvertiseSettings settingsInEffect) { 
       super.onStartSuccess(settingsInEffect); 
      } 

      @Override 
      public void onStartFailure(int errorCode) { 
       Log.e("BLE_code", "Advertising onStartFailure: " + errorCode); 
       super.onStartFailure(errorCode); 
      } 
     }; 

     //BLE Button 

     btn.setOnTouchListener(new View.OnTouchListener() { 
      private Handler mHandler; 
      @Override 
      public boolean onTouch(View view, MotionEvent motionEvent) { 

       switch (motionEvent.getAction()) 
       { 
        case MotionEvent.ACTION_DOWN: 
         Log.e("BLE_code","Button is being pressed"); 
         Log.e("BLE_code", "State ble: " + mBluetoothAdapter.getState()); 
         ParcelUuid pUuid = new ParcelUuid(UUID.fromString(getString(R.string.ble_uuid))); 
         AdvertiseData data = new AdvertiseData.Builder() 
           .setIncludeDeviceName(true) 
           .addServiceUuid(pUuid) 
           .addServiceData(pUuid,edit.getText().toString().getBytes(Charset.forName("UTF-8"))) 
           .build(); 

         Log.e("BLE_code", "Sent Data: " + edit.getText().toString()); 
         String macAddress = android.provider.Settings.Secure.getString(getContentResolver(),"bluetooth_address"); 
         Toast.makeText(getApplicationContext(),"Device: " + macAddress, Toast.LENGTH_SHORT).show(); 
         mBluetoothLeAdvertiser.startAdvertising(settings, data, advertisingCallback); 
         //advertiser.startAdvertising(settings, data, advertisingCallback); 

         if (mHandler!=null) return true; 
         mHandler = new Handler(); 
         mHandler.postDelayed(btn_pressed,10); 
         break; 
        case MotionEvent.ACTION_UP: 
         if(mHandler==null) return true; 
         mHandler.removeCallbacks(btn_pressed); 
         mHandler = null; 
         advertiser.stopAdvertising(advertisingCallback); 
         Toast.makeText(getApplicationContext(),"Stoping Advertising", Toast.LENGTH_SHORT).show(); 
         Log.e("BLE_code","Button was released"); 
         break; 
       } 
       return false; 
      } 

      Runnable btn_pressed = new Runnable() { 
       public void run(){ 
        Log.e("BLE_code","Button while pressed"); 
        mHandler.postDelayed(this,10); 
       } 
      }; 
     }); 
    } 
} 

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.ble_app.aecheverri.ble_app.MainActivity"> 

    <Button 
     android:id="@+id/BLE_CHECK_button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="8dp" 
     android:layout_marginRight="8dp" 
     android:layout_marginTop="195dp" 
     android:text="Authenticate" 
     app:layout_constraintLeft_toLeftOf="parent" 
     app:layout_constraintRight_toRightOf="parent" 
     app:layout_constraintTop_toTopOf="parent" 
     app:layout_constraintHorizontal_bias="0.474" /> 

    <android.support.constraint.Guideline 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/guideline" 
     app:layout_constraintGuide_begin="20dp" 
     android:orientation="vertical" /> 

    <android.support.constraint.Guideline 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/guideline2" 
     android:orientation="vertical" 
     app:layout_constraintGuide_end="340dp" /> 

    <EditText 
     android:id="@+id/Data_Sent" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:ems="10" 
     android:inputType="text" 
     android:text="Data" 
     android:layout_marginTop="8dp" 
     app:layout_constraintTop_toTopOf="parent" 
     android:layout_marginBottom="8dp" 
     app:layout_constraintBottom_toTopOf="@+id/BLE_CHECK_button" 
     app:layout_constraintVertical_bias="0.683" 
     android:layout_marginLeft="8dp" 
     app:layout_constraintLeft_toLeftOf="parent" 
     android:layout_marginRight="8dp" 
     app:layout_constraintRight_toRightOf="parent" 
     app:layout_constraintHorizontal_bias="0.503" /> 

</android.support.constraint.ConstraintLayout> 

的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.ble_app.aecheverri.ble_app"> 


    <!-- Declare this required feature if you want to make the app available to BLE-capable 
    devices only. If you want to make your app available to devices that don't support BLE, 
    you should omit this in the manifest. Instead, determine BLE capability by using 
    PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) --> 

    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS"/> 
    <uses-permission android:name="android.permission.BLUETOOTH"/> 
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:roundIcon="@mipmap/ic_launcher_round" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme"> 
     <activity android:name=".MainActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

的strings.xml

<resources> 
    <string name="app_name">BLE_app</string> 
    <string name="ble_uuid">00000218-0000-1000-8000-00805f9b34fb</string> 
</resources> 

记录错误

08-17 13:55:25.533 13469-13469/com.ble_app.aecheverri.ble_app E/BoostFramework: BoostFramework() : Exception_1 = java.lang.ClassNotFoundException: Didn't find class "com.qualcomm.qti.Performance" on path: DexPathList[[],nativeLibraryDirectories=[/system/lib64, /vendor/lib64]] 
08-17 13:55:25.566 13469-13469/com.ble_app.aecheverri.ble_app E/InputEventReceiver: Exception dispatching input event. 
08-17 13:55:25.567 13469-13469/com.ble_app.aecheverri.ble_app E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback 
08-17 13:55:25.569 13469-13469/com.ble_app.aecheverri.ble_app E/MessageQueue-JNI: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.le.BluetoothLeAdvertiser.startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback)' on a null object reference 
                         at com.ble_app.aecheverri.ble_app.MainActivity$2.onTouch(MainActivity.java:101) 
                         at android.view.View.dispatchTouchEvent(View.java:10727) 
                         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                         at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:509) 
                         at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1863) 
                         at android.app.Activity.dispatchTouchEvent(Activity.java:3226) 
                         at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) 
                         at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:471) 
                         at android.view.View.dispatchPointerEvent(View.java:10960) 
                         at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5075) 
                         at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4927) 
                         at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4458) 
                         at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4511) 
                         at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4477) 
                         at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4610) 
                         at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4485) 
                         at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4667) 
                         at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4458) 
                         at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4511) 
                         at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4477) 
                         at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4485) 
                         at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4458) 
                         at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6960) 
                         at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6899) 
                         at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6860) 
                         at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7070) 
                         at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) 
                         at android.os.MessageQueue.nativePollOnce(Native Method) 
                         at android.os.MessageQueue.next(MessageQueue.java:323) 
                         at android.os.Looper.loop(Looper.java:136) 
                         at android.app.ActivityThread.main(ActivityThread.java:6692) 
                         at java.lang.reflect.Method.invoke(Native Method) 
                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 
08-17 13:55:25.571 13469-13469/com.ble_app.aecheverri.ble_app E/AndroidRuntime: FATAL EXCEPTION: main 
                       Process: com.ble_app.aecheverri.ble_app, PID: 13469 
                       java.lang.NullPointerException: Attempt to invoke virtual method 'void android.bluetooth.le.BluetoothLeAdvertiser.startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback)' on a null object reference 
                        at com.ble_app.aecheverri.ble_app.MainActivity$2.onTouch(MainActivity.java:101) 
                        at android.view.View.dispatchTouchEvent(View.java:10727) 
                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2865) 
                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2492) 
                        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:509) 
                        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1863) 
                        at android.app.Activity.dispatchTouchEvent(Activity.java:3226) 
                        at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) 
                        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:471) 
                        at android.view.View.dispatchPointerEvent(View.java:10960) 
                        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5075) 
                        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4927) 
                        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4458) 
                        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4511) 
                        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4477) 
                        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4610) 
                        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4485) 
                        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4667) 
                        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4458) 
                        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4511) 
                        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4477) 
                        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4485) 
                        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4458) 
                        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6960) 
                        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6899) 
                        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6860) 
                        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7070) 
                        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) 
                        at android.os.MessageQueue.nativePollOnce(Native Method) 
                        at android.os.MessageQueue.next(MessageQueue.java:323) 
                        at android.os.Looper.loop(Looper.java:136) 
                        at android.app.ActivityThread.main(ActivityThread.java:6692) 
                        at java.lang.reflect.Method.invoke(Native Method) 
                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 
+0

寻求调试帮助的问题(“为什么不是这个代码工作?”)必须包含所需的行为,特定的问题或错误以及在问题本身中重现问题所需的最短代码。没有明确问题陈述的问题对其他读者无益。请参阅:[如何创建最小,完整和可验证的示例。](https://stackoverflow.com/help/mcve) – Bob

+0

感谢您的建议。我试图让自己尽可能清楚。在程序中,有一个按钮被按下,应用程序崩溃。 – aecheverri

+0

然后请发布您的崩溃日志。 – Bob

BluetoothLeAdvertiser advertiser有空引用。可能是因为你的BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser()返回null。

+0

我看到在日志中,你是对的。但是,我可以创建一个条件来检查它是否为空或者它是否启用,如下所示: if(mBluetoothAdapter == null || mBluetoothAdapter.isEnabled()) – aecheverri

+0

选中此项:https://stackoverflow.com/ a/37938934/4586742 – Bob

+0

我刚刚在代码中添加了以下几行代码(查看更新的代码,我检查了所有在帖子中完成的建议)。仍然崩溃,我知道我的设备支持蓝牙和BLE作为外设。但是,一旦启用,BluetoothAdpter不应为空。除此以外。我应该如何分配BluetoothAdpter? – aecheverri