java - Android:在蓝牙应用程序的单个 APK 上支持多个 API 级别

标签 java android bluetooth

我开发了一款在 Jelly Bean(Android 4.3) 上使用蓝牙功能的应用程序。我注意到 Lollipop 的蓝牙类有一组不同的方法。当我在 Lollipop 上运行我的应用程序时,它失败了。

我了解到我可以添加代码以在运行时支持不同的 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,它在我的 Activity 类中但在任何方法之外。

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 来支持 Lollipop,所以我添加了另一个这样的回调:

    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);
                }
            }
        }
     };

它现在可以在 Lollipop 中运行,但是当我在 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

更新 感谢@Jesse 指出我可以在回调中添加用于检查构建版本的代码。可以成功构建APK,但现在无法在4.4.2中运行

最佳答案

你很接近。 BluetoothAdapter.LeScanCallback 是一个接口(interface)。当你这样做时:

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);
                            }
                        });

                    }
                });
            }
        };

“它在 [您的] Activity 类中,但在任何方法之外。”这段代码实际上没有发生任何事情。当你调用它时:

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);
    }
}

关于java - Android:在蓝牙应用程序的单个 APK 上支持多个 API 级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38237229/

相关文章:

java - 不知道该写什么作为我的返回单?

java - DispatcherServlet 中的 ThreadLocal

java - Apk 未安装在 Oreo 上

android - android 设备上 sqlite 数据库的默认位置不显示我的数据库

android - bindservice 中的 onServiceConnected 只被调用一次

java - 帮助为 Maven、ANT Build 等工具提供良好的入门引用

java - 获取AsyncTask的结果而不阻塞线程

iphone - 如何以编程方式更改 iPhone 的蓝牙参数?

android - 如何从 Android 中的 TTF 文件读取字距调整对表

java - 我如何实现setonmenuitemclicklistener?