1

我有一个问题是指 java 编译器行为以及 android 的不同 API。

我有代表蓝牙 LE 连接的课程。我在这个类中检查 API 的版本,以了解我必须使用哪些方法来扫描设备。这里是:

public class BleConnector{

    private MyScanCallback _scanCallback;


private LeScanHandle _leScanHndl;
private BluetoothAdapter _bluetoothAdapter;

/**
 * Initializes new instance of BLE connector
 */
public BleConnector()
{
    //Creating handle for device scan callback;
    _leScanHndl = new LeScanHandle();

    //Check version of android api
    //If it is bigger of equal to 21
    //create scan callback for higher versions
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        _scanCallback = new ScanCallback(_leScanHndl);
    }
}


public void startScan(Context context) throws PermissoinException
{
    final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
    _bluetoothAdapter = bluetoothManager.getAdapter();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)
        {
            _bluetoothAdapter.getBluetoothLeScanner().startScan(_scanCallback);
        }
        else
        {
             throw new PermissoinException("Location permission does not allowed");
        }
    }
    else
    {
        _bluetoothAdapter.startLeScan(_leScanHndl);
    }
    //TODO notify
}

public void stopScan()
{
    if (_bluetoothAdapter != null)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
        {
           _bluetoothAdapter.getBluetoothLeScanner().stopScan(_scanCallback);
        } else
        {
            _bluetoothAdapter.stopLeScan(_leScanHndl);
        }
    }

    //TODO notify
}

private void connectToDevice(BluetoothDevice device)
{
    //TODO notify

   //TODO connect gatt
}

MyScanCallback 类标有@TargetAPI 21,如果我的设备版本低于 21,我当然不想使用它

如您所见,_scanCallback的所有用法和初始化都在if语句中。所以我的问题是:

private MyScanCallback _scanCallback;如果没有_scanCallback的初始化和使用,我会在 api<21 的设备上声明有任何问题 吗?或者编译器会删除它?

谢谢!

UDT

哦,我没有说 MyScanCallback 继承了 ScanCallback ,它来自 21 API 级别public class MyScanCallback extends ScanCallback

4

1 回答 1

2

@TargetApi 21 只是为了防止使用的任何新 API 出现任何编译错误。Byt 要真正避免执行代码,它必须像您在几个地方所做的那样围绕构建版本检查进行。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
}

所以在这种情况下,肯定会创建一个 MyScanCallback 变量,但它不会在 api<21 的设备上实例化,因为您已经将它包装在构造函数中的版本检查周围。

正如您提到的,它使用的是 API 21 中引入的 ScanCallback,那么在旧版本中使用它肯定会是一个问题。

为了摆脱这种情况,我建议创建一个抽象类,如下所示:

public abstract class BleConnector{

public abstract void startScan(Context context);

}

然后创建两个类

public class BleConnectOldApi extends BleConnector{
public void startScan(Context context) throws PermissoinException {
//Your code here
}
}

@TargetApi(21)
public class BleConnect21Api extends BleConnector{

private MyScanCallback _scanCallback;

public void startScan(Context context) throws PermissoinException {
//Your code here
}
}

终于有工厂课了

public class BleConnectorFactory{

    public static BleConnector getBleConnector() {

        if (android.os.Build.VERSION.SDK_INT >= 21) {
            return new BleConnect21Api();
        }else{
            return new BleConnectOldApi();
        }

    }
}

这样,您可以防止因使用旧 API 版本中不存在的类而出现不必要的错误。

希望对您有所帮助。

于 2016-06-28T16:49:59.010 回答