2016-07-07 80 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