2016-07-07 81 views
1

我開發了一個應用程序,它使用Jelly Bean(Android 4.3)上的藍牙功能。我注意到棒棒糖的藍牙類有一套不同的方法。當我在棒棒糖上運行我的應用程序時,它失敗了。Android:支持單個APK的多個API級別藍牙應用程序

我瞭解到,我可以添加代碼以支持在運行不同的API級別,如:

private void startScanBluetooth(){ 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     // Method supported in Lollipop 
     mLeScanner.stopScan(mScanCallback); 
    } 
    else { 
     // Method for older API level 
     mBluetoothAdapter.stopLeScan(mLeScanCallback); 
    } 
} 

我的代碼有一個BluetoothAdapter.LeScanCallback這是在我的活動類,但任何方法之外。

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar); 
    setContentView(R.layout.device_list); 

    final BluetoothManager bluetoothManager = 
      (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 
    mBluetoothAdapter = bluetoothManager.getAdapter(); 
    //.... 
} 

private BluetoothAdapter.LeScanCallback mLeScanCallback = 
     new BluetoothAdapter.LeScanCallback() { 

      @Override 
      public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 

         runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 
           //String targetDevice = MainActivity.targetDevice.getText().toString(); 
           //if(targetDevice==null || targetDevice.length()==0 || targetDevice.equals(device.getName())) 
           addDevice(device,rssi); 
          } 
         }); 

        } 
       }); 
      } 
     }; 

由於這個回調已過時,我需要一個新的回調方法:ScanCallBack支持棒棒堂,所以我增加了一個回調是這樣的:但是

mScanCallback = new ScanCallback() { 
     @Override 
     public void onScanResult(int callbackType, ScanResult result) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       Log.i("callbackType", String.valueOf(callbackType)); 
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
        Log.i("result", result.toString()); 
        BluetoothDevice btDevice = result.getDevice(); 
        connectToDevice(btDevice); 
       } 
      } 
     } 
    }; 

現在它可以在棒棒糖運行,當我在4.4.2上運行它時,應用程序一旦運行DeviceListActivity(以上所有內容均位於此類中),它就會出現意外。日誌失敗時爲:

09-02 17:42:46.469 15329-15329/com.conerstoneee2.blecaller D/OLED: Start DeviceListActivity now 
09-02 17:42:46.499 15329-15329/com.conerstoneee2.blecaller D/OLED: onPause 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: Unable to resolve superclass of Lcom/conerstoneee2/blecaller/DeviceListActivity$3; (63) 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: Link of class 'Lcom/conerstoneee2/blecaller/DeviceListActivity$3;' failed 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller E/dalvikvm: Could not find class 'com.conerstoneee2.blecaller.DeviceListActivity$3', referenced from method com.conerstoneee2.blecaller.DeviceListActivity.<init> 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to resolve new-instance 1960 (Lcom/conerstoneee2/blecaller/DeviceListActivity$3;) in Lcom/conerstoneee2/blecaller/DeviceListActivity; 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: VFY: replacing opcode 0x22 at 0x0006 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to find class referenced in signature (Landroid/bluetooth/le/ScanCallback;) 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller I/dalvikvm: Could not find method android.bluetooth.le.BluetoothLeScanner.startScan, referenced from method com.conerstoneee2.blecaller.DeviceListActivity.scanLeDevice 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to resolve virtual method 311: Landroid/bluetooth/le/BluetoothLeScanner;.startScan (Landroid/bluetooth/le/ScanCallback;)V 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: VFY: replacing opcode 0x6e at 0x0024 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller I/dalvikvm: Could not find method android.bluetooth.le.BluetoothLeScanner.stopScan, referenced from method com.conerstoneee2.blecaller.DeviceListActivity.scanLeDevice 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to resolve virtual method 312: Landroid/bluetooth/le/BluetoothLeScanner;.stopScan (Landroid/bluetooth/le/ScanCallback;)V 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: VFY: replacing opcode 0x6e at 0x0041 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller I/dalvikvm: Could not find method android.bluetooth.BluetoothAdapter.getBluetoothLeScanner, referenced from method com.conerstoneee2.blecaller.DeviceListActivity.onCreate 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to resolve virtual method 283: Landroid/bluetooth/BluetoothAdapter;.getBluetoothLeScanner()Landroid/bluetooth/le/BluetoothLeScanner; 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: VFY: replacing opcode 0x6e at 0x0071 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller I/dalvikvm: Could not find method android.bluetooth.le.BluetoothLeScanner.stopScan, referenced from method com.conerstoneee2.blecaller.DeviceListActivity.onDestroy 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to resolve virtual method 312: Landroid/bluetooth/le/BluetoothLeScanner;.stopScan (Landroid/bluetooth/le/ScanCallback;)V 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: VFY: replacing opcode 0x6e at 0x0014 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller I/dalvikvm: Could not find method android.bluetooth.le.BluetoothLeScanner.stopScan, referenced from method com.conerstoneee2.blecaller.DeviceListActivity.onStop 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: VFY: unable to resolve virtual method 312: Landroid/bluetooth/le/BluetoothLeScanner;.stopScan (Landroid/bluetooth/le/ScanCallback;)V 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: VFY: replacing opcode 0x6e at 0x0014 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: Unable to resolve superclass of Lcom/conerstoneee2/blecaller/DeviceListActivity$3; (63) 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: Link of class 'Lcom/conerstoneee2/blecaller/DeviceListActivity$3;' failed 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/dalvikvm: DexOpt: unable to opt direct call 0x3ea0 at 0x08 in Lcom/conerstoneee2/blecaller/DeviceListActivity;.<init> 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller D/AndroidRuntime: Shutting down VM 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41f8bda0) 
09-02 17:42:46.519 15329-15329/com.conerstoneee2.blecaller E/AndroidRuntime: FATAL EXCEPTION: main 
                      Process: com.conerstoneee2.blecaller, PID: 15329 
                      java.lang.NoClassDefFoundError: com.conerstoneee2.blecaller.DeviceListActivity$3 
                       at com.conerstoneee2.blecaller.DeviceListActivity.<init>(DeviceListActivity.java:181) 
                       at java.lang.Class.newInstanceImpl(Native Method) 
                       at java.lang.Class.newInstance(Class.java:1208) 
                       at android.app.Instrumentation.newActivity(Instrumentation.java:1067) 
                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2289) 
                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2453) 
                       at android.app.ActivityThread.access$900(ActivityThread.java:173) 
                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) 
                       at android.os.Handler.dispatchMessage(Handler.java:102) 
                       at android.os.Looper.loop(Looper.java:136) 
                       at android.app.ActivityThread.main(ActivityThread.java:5579) 
                       at java.lang.reflect.Method.invokeNative(Native Method) 
                       at java.lang.reflect.Method.invoke(Method.java:515) 
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) 
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
                       at dalvik.system.NativeStart.main(Native Method) 
09-02 17:42:49.959 15329-15329/com.conerstoneee2.blecaller I/Process: Sending signal. PID: 15329 SIG: 9 

UPDATE 感謝@Jesse指出的是,我可以添加代碼檢查回調內部的內部版本。它可以成功構建APK,但現在無法在4.4.2中運行。

+0

AFAIK這是你可以使用舊的以及新的API的其他方式不推薦的唯一途徑是減少編譯和目標SDK到最小SDK版本 – dex

+0

那麼什麼樣的異常/錯誤的當你嘗試發佈第一個代碼片段時,你會得到嗎? – RafToTheK

回答

1

你很近。 BluetoothAdapter.LeScanCallback是一個接口。當你這樣做:

private BluetoothAdapter.LeScanCallback mLeScanCallback = 
     new BluetoothAdapter.LeScanCallback() { 

      @Override 
      public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 

         runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 
           //String targetDevice = MainActivity.targetDevice.getText().toString(); 
           //if(targetDevice==null || targetDevice.length()==0 || targetDevice.equals(device.getName())) 
           addDevice(device,rssi); 
          } 
         }); 

        } 
       }); 
      } 
     }; 

「這是在[你的]活動類,但在任何方法之外。」這段代碼沒有真正發生。當你這樣稱呼:

mLeScanner.stopScan(mScanCallback); 

並作爲參數傳遞它。 mLeScanner在需要時使用該回調。

所以,只需創建您的附加回調方法(不要檢查構建版本)。

private **typeNameGoesHere** mScanCallback = new ScanCallback() { 
     @Override 
     public void onScanResult(int callbackType, ScanResult result) { 
      Log.i("callbackType", String.valueOf(callbackType)); 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       Log.i("result", result.toString()); 
       BluetoothDevice btDevice = result.getDevice(); 
       connectToDevice(btDevice); 
      } 
     } 
    }; 

然後保持你的startScanBluetooth方法,你應該沒問題。

private void startScanBluetooth(){ 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     // Method supported in Lollipop 
     mLeScanner.stopScan(mScanCallback); 
    } 
    else { 
     // Method for older API level 
     mBluetoothAdapter.stopLeScan(mLeScanCallback); 
    } 
} 
+0

謝謝,我現在可以添加Lollipop的回調。儘管在使用Android 6設備時我仍然無法掃描藍牙設備。 – eepty

+0

我還沒有升級到6,但我認爲這個通話改變了。查看[this](https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html) – Jesse

+0

最後我發現Android 6中有一個巨大的變化。我發現我需要在運行時獲得許可,並且需要獲得掃描藍牙設備的位置權限。 – eepty