2017-08-17 195 views
-2

我希望有人可以給我一個關於這個問題的建議。我一直試圖解決它沒有任何運氣,我也看到這是一個真正的問題,並有很多討論。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

回答

0

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