适当的方式使用MVVM和架构组件?

时间:2018-01-15 17:37:21

标签: android mvvm bluetooth-lowenergy

我正在使用蓝牙LE设备,我正在考虑我目前的做法和最佳做法。目前我有一个处理连接和GattCallbacks的活动,我决定重新构建代码以获得更好的概述和可维护性,因为它实际上非常混乱。

我从NordicSemiconductor https://github.com/NordicSemiconductor/Android-BLE-Library/

找到了BleManager

它是连接BLE设备的基本步骤的抽象,它处理GattCallbacks +提供从服务或ViewModel使用它的适当接口。

我想使用ViewModel方法,但我对MVC,MVP,MVVM模式并不熟悉,还有一些我仍然无法回复的问题

此类正在扩展BleManager(BlinkyManager.java

它展示了如何使用BleManager,因此我采用了这个类并将其命名为ECountBleManager

编辑:
在过去的6天里,我特别面对MVVM模式和架构组件进行了重新研究。不幸的是,我仍然有许多问题无法自行回复。但我真的想要变得更好,所以我草拟了我当前的概念。我希望你能帮助我回答我的问题并改进我的项目。

我对最佳做法特别感兴趣。

这是我的草稿:

enter image description here

这是我的班级实施:
ECountActivity.java

public class ECountActivity extends AppCompatActivity {

    private ECountViewModel viewModel;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.detail_view);

        // hide magnifier icon
        GifImageView customLoader = findViewById(R.id.progressBar);
        customLoader.setVisibility(View.GONE);

        // Get additional data from previous activity
        final BluetoothDevice device = getIntent().getParcelableExtra("device");

        initViewModel();
        viewModel.connect(device);
    }

    private void initViewModel() {
        viewModel = ViewModelProviders.of(this).get(ECountViewModel.class);
        subscribeDataStreams(viewModel);
    }

    private void subscribeDataStreams(ECountViewModel viewModel) {
        viewModel.isDeviceReady().observe(this, deviceReady -> openOptionsFragment());


        viewModel.isConnected().observe(this, status -> {
            // Todo: ...
        });
    }

    private void openOptionsFragment() {
        // load options fragment
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.contentFragment, new OptionsFragment());
        ft.commitNow();
    }

}

OtaFragment.java

public class OtaFragment extends Fragment implements FolderChooserDialog.FolderCallback,
        FileChooserDialog.FileCallback {

    private Button partialOtaButton;
    private Button fullOtaButton;
    private Button submitButton;
    private SeekBar mtuSeekBar;
    private EditText mtuInput;
    private LinearLayout stacklayout;
    private Button browseAppButton;
    private TextView folderPathText;
    private TextView appFileNameText;

    private MaterialDialog otaPrepareDialog;
    private MaterialDialog otaProgressDialog;

    private ECountViewModel viewModel;
    private OtaViewModel otaViewModel;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initViewModel();
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // inflate the layout for this fragment
        View view = inflater.inflate(R.layout.ota_fragment, container, false);
        initViews(view);
        return view;
    }

    @Override
    public void onFolderSelection(@NonNull FolderChooserDialog dialog, @NonNull File folder) {
        final String otaFolderPath = folder.toString();
        otaViewModel.setOtaFolderPath(otaFolderPath);
        folderPathText.setText(otaFolderPath.substring(otaFolderPath.lastIndexOf("/")));
        // enable app browse
        browseAppButton.setClickable(true);
        browseAppButton.setEnabled(true);
    }

    @Override
    public void onFolderChooserDismissed(@NonNull FolderChooserDialog dialog) {}

    @Override
    public void onFileSelection(@NonNull FileChooserDialog dialog, @NonNull File file) {
        final String otaAppFilePath = file.toString();
        otaViewModel.setOtaAppFilePath(otaAppFilePath);
        appFileNameText.setText(otaAppFilePath.substring(otaAppFilePath.lastIndexOf("/")));
        // enable submitButton button
        submitButton.setClickable(true);
        submitButton.setEnabled(true);
    }

    @Override
    public void onFileChooserDismissed(@NonNull FileChooserDialog dialog) {}

    private void subscribeDataStreams(ECountViewModel viewModel) {
        viewModel.isOtaMode().observe(this, otaMode -> {
            otaPrepareDialog.dismiss();
            initOtaProgressDialog();
            otaProgressDialog.show();

            // Todo: how can i get mtu?
            viewModel.requestMtu(512);
        });
    }

    private void initViewModel() {
        viewModel = ViewModelProviders.of(getActivity()).get(ECountViewModel.class);
        otaViewModel = ViewModelProviders.of(getActivity()).get(OtaViewModel.class);
        subscribeDataStreams(viewModel);
    }

    private void initViews(View view) {
        // get resources
        final Button browseFolderButton = view.findViewById(R.id.browseFolder);
        final Button cancelButton = view.findViewById(R.id.ota_cancel);
        final SeekBar prioritySeekBar = view.findViewById(R.id.connection_seekBar);
        partialOtaButton = view.findViewById(R.id.radio_ota);
        fullOtaButton = view.findViewById(R.id.radio_ota_full);
        browseAppButton = view.findViewById(R.id.browseApp);
        folderPathText = view.findViewById(R.id.folderPathText);
        appFileNameText = view.findViewById(R.id.appFileNameText);
        stacklayout = view.findViewById(R.id.stacklayout);
        submitButton = view.findViewById(R.id.ota_proceed);
        mtuSeekBar = view.findViewById(R.id.mtu_seekBar);
        mtuInput = view.findViewById(R.id.mtu_value);

        // set initial states
        mtuSeekBar.setMax(512-23);
        mtuSeekBar.setProgress(244);
        prioritySeekBar.setMax(2);
        prioritySeekBar.setProgress(1);
        browseAppButton.setClickable(false);
        browseAppButton.setEnabled(false);
        submitButton.setClickable(false);
        submitButton.setEnabled(false);

        mtuInput.setOnEditorActionListener((v, actionId, event) -> {
            final Editable mtuText = mtuInput.getText();
            if (mtuText != null) {
                int mtu = Integer.valueOf(mtuText.toString());
                if (mtu < 23)  mtu = 23;
                if (mtu > 512) mtu = 512;
                mtuSeekBar.setProgress(mtu);
                viewModel.setMtu(mtu);
            }
            return false;
        });


        mtuSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mtuInput.setText(String.valueOf(progress));
                viewModel.setMtu(progress);
            }
        });

        prioritySeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                viewModel.setPriority(progress);
            }
        });

        browseFolderButton.setOnClickListener(v -> new FolderChooserDialog.Builder(getActivity())
                .chooseButton(R.string.positiveTextChoose)
                .tag("#folder")
                .show(getChildFragmentManager()));

        browseAppButton.setOnClickListener(v -> new FileChooserDialog.Builder(getActivity())
                .initialPath(otaViewModel.getOtaFolderPath())
                .extensionsFilter(".ebl")
                .tag("#app")
                .show(getChildFragmentManager()));

        cancelButton.setOnClickListener(v -> Log.i("ota", "cancelButton"));

        submitButton.setOnClickListener(v -> {
            // disable OTA submitButton button
            submitButton.setClickable(false);
            submitButton.setEnabled(false);
            // init OTA process
            viewModel.initOtaMode();
            // show OTA preparing dialog
            otaPrepareDialog.show();
        });

        fullOtaButton.setOnClickListener(v -> {
            stacklayout.setVisibility(View.VISIBLE);
            partialOtaButton.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
            fullOtaButton.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
        });

        partialOtaButton.setOnClickListener(v -> {
            stacklayout.setVisibility(View.GONE);
            partialOtaButton.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
            fullOtaButton.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
        });

        otaPrepareDialog = new MaterialDialog.Builder(getActivity())
                .title(R.string.otaDialogHeaderText)
                .content(R.string.waiting)
                .progress(true, 0)
                .progressIndeterminateStyle(true)
                .build();

        otaProgressDialog = new MaterialDialog.Builder(getActivity())
                .title("test")
                .customView(R.layout.ota_progress2, false)
                .build();
    }

    private void initOtaProgressDialog() {
        // Todo: ...
    }
}

ECountViewModel.java

public class ECountViewModel extends AndroidViewModel implements ECountBleManagerCallbacks {
    private final ECountBleManager eCountBleManager;

    // Connection states Connecting, Connected, Disconnecting, Disconnected etc.
    private final MutableLiveData<String> connectionState = new MutableLiveData<>();

    // Flag to determine if the device is connected
    private final MutableLiveData<Boolean> isConnected = new MutableLiveData<>();

    // Flag to determine if the device is ready
    private final MutableLiveData<Void> onDeviceReady = new MutableLiveData<>();

    // Flag to determine if the device is in OTA mode
    private final MutableLiveData<Void> onOtaMode = new MutableLiveData<>();


    public LiveData<Void> isDeviceReady() {
        return onDeviceReady;
    }

    public LiveData<Void> isOtaMode() {
        return onOtaMode;
    }

    public LiveData<String> getConnectionState() {
        return connectionState;
    }

    public LiveData<Boolean> isConnected() {
        return isConnected;
    }

    public ECountViewModel(@NonNull final Application application) {
        super(application);

        // Initialize the manager
        eCountBleManager = new ECountBleManager(getApplication());
        eCountBleManager.setGattCallbacks(this);
    }

    /**
     * Connect to peripheral
     */
    public void connect(final BluetoothDevice device) {
        eCountBleManager.connect(device);
    }

    /**
     * Disconnect from peripheral
     */
    private void disconnect() {
        eCountBleManager.disconnect();
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        if (eCountBleManager.isConnected()) {
            disconnect();
        }
    }

    @Override
    public void onDeviceConnecting(BluetoothDevice device) {
    }

    @Override
    public void onDeviceConnected(BluetoothDevice device) {
        isConnected.postValue(true);
    }

    @Override
    public void onDeviceDisconnecting(BluetoothDevice device) {
        isConnected.postValue(false);
    }

    @Override
    public void onDeviceDisconnected(BluetoothDevice device) {
        isConnected.postValue(false);
    }

    @Override
    public void onLinklossOccur(BluetoothDevice device) {
        isConnected.postValue(false);
    }

    @Override
    public void onServicesDiscovered(BluetoothDevice device, boolean optionalServicesFound) {
    }

    @Override
    public void onDeviceReady(BluetoothDevice device) {
        onDeviceReady.postValue(null);
    }

    @Override
    public void onOptionalServiceSupported(BluetoothDevice device) {
        onOtaMode.postValue(null);
    }

    @Override
    public void onBondingRequired(BluetoothDevice device) {

    }

    @Override
    public void onBonded(BluetoothDevice device) {

    }

    @Override
    public void onError(BluetoothDevice device, String message, int errorCode) {

    }

    @Override
    public void onDeviceNotSupported(BluetoothDevice device) {
        disconnect();
    }

    // delegate call from options fragment to ECountBleManager
    public String getDeviceId() {
        return BinaryUtils.byteArrayToHexString(eCountBleManager.getDeviceId());
    }

    // delegate call from ota fragment to ECountBleManager
    public void setMtu(final int value) {
        eCountBleManager.setMtu(value);
    }

    public void setPriority(final int value) {
        eCountBleManager.setPriority(value);
    }

ECountBleManager.java

public class ECountBleManager extends BleManager<BleManagerCallbacks> {

    private static final String TAG = ECountBleManager.class.getSimpleName();
    private final Handler handler;

    private BluetoothGattCharacteristic authCharacteristic;
    private BluetoothGattCharacteristic deviceIdCharacteristic;
    private BluetoothGattCharacteristic deviceVersionCharacteristic;
    private BluetoothGattCharacteristic configIdCharacteristic;
    private BluetoothGattCharacteristic configTransmissionIntervalCharacteristic;
    private BluetoothGattCharacteristic configKeepAliveIntervalCharacteristic;
    private BluetoothGattCharacteristic configRadioModeCharacteristic;
    private BluetoothGattCharacteristic configGpsCharacteristic;
    private BluetoothGattCharacteristic configRadarCharacteristic;
    private BluetoothGattCharacteristic configOperationModeCharacteristic;
    private BluetoothGattCharacteristic configLoRaAppEuiCharacteristic;
    private BluetoothGattCharacteristic configLoRaAppKeyCharacteristic;
    private BluetoothGattCharacteristic configLoRaDeviceEuiCharacteristic;
    private BluetoothGattCharacteristic operationCmdCharacteristic;
    private BluetoothGattCharacteristic nemeusStatusCharacteristic;
    private BluetoothGattCharacteristic gmrStatusCharacteristic;
    private BluetoothGattCharacteristic radarStatusCharacteristic;
    private BluetoothGattCharacteristic otaControlCharacteristic;
    private BluetoothGattCharacteristic otaDataCharacteristic;

    private byte[] configTransmissionInterval;
    private byte[] configKeepAliveInterval;
    private byte[] configRadioMode;
    private byte[] configOperationMode;
    private byte[] configId;
    private byte[] deviceId;
    private byte[] deviceVersion;
    private byte[] configGps;
    private byte[] configRadar;
    private byte[] configLoRaAppEui;
    private byte[] configLoRaAppKey;
    private byte[] configLoRaDeviceEui;
    private byte[] operationCmd;
    private byte[] nemeusStatus;
    private byte[] gmrStatus;
    private byte[] radarStatus;

    // OTA flags
    private boolean isOtaProcessing = false;
    private boolean isReconnectRequired = false;
    private MutableLiveData<Boolean> isOtaMode = new MutableLiveData<>();
    // OTA variables
    private int mtu = 512;
    private int priority = BluetoothGatt.CONNECTION_PRIORITY_HIGH;
    private byte[] otaAppFileStream;
    ////////////////////////////

    public ECountBleManager(Context context) {
        super(context);
        handler = new Handler();
    }

    @Override
    protected BleManagerGattCallback getGattCallback() {
        return gattCallback;
    }

    @Override
    protected boolean shouldAutoConnect() {
        return true;
    }

    /**
     * BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc
     */
    private final BleManagerGattCallback gattCallback = new BleManagerGattCallback() {

        @Override
        protected void onDeviceReady() {
            super.onDeviceReady();
        }

        @Override
        protected void onOptionalServiceSupported() {
            super.onOptionalServiceSupported();
            isOtaMode.postValue(true);
        }

        @Override
        protected boolean isOptionalServiceSupported(BluetoothGatt gatt) {
            final BluetoothGattService otaService = gatt.getService(DC_UUID.otaService);
            otaDataCharacteristic = otaService.getCharacteristic(DC_UUID.otaData);
            return otaDataCharacteristic != null;
        }

        @Override
        protected boolean isRequiredServiceSupported(BluetoothGatt gatt) {
            final BluetoothGattService dcService = gatt.getService(DC_UUID.dcService);
            final BluetoothGattService otaService = gatt.getService(DC_UUID.otaService);

            if (dcService == null || otaService == null) return false;

            authCharacteristic = dcService.getCharacteristic(DC_UUID.authentication);
            deviceIdCharacteristic = dcService.getCharacteristic(DC_UUID.deviceId);
            deviceVersionCharacteristic = dcService.getCharacteristic(DC_UUID.deviceVersion);
            configIdCharacteristic = dcService.getCharacteristic(DC_UUID.configId);
            configTransmissionIntervalCharacteristic = dcService.getCharacteristic(DC_UUID.configTransmissionInterval);
            configKeepAliveIntervalCharacteristic = dcService.getCharacteristic(DC_UUID.configKeepAliveInterval);
            configRadioModeCharacteristic = dcService.getCharacteristic(DC_UUID.configRadioMode);
            configGpsCharacteristic = dcService.getCharacteristic(DC_UUID.configGps);
            configRadarCharacteristic = dcService.getCharacteristic(DC_UUID.configRadar);
            configOperationModeCharacteristic = dcService.getCharacteristic(DC_UUID.configOperationMode);
            configLoRaAppEuiCharacteristic = dcService.getCharacteristic(DC_UUID.configLoRaAppEui);
            configLoRaAppKeyCharacteristic = dcService.getCharacteristic(DC_UUID.configLoRaAppKey);
            configLoRaDeviceEuiCharacteristic = dcService.getCharacteristic(DC_UUID.configLoRaDeviceEui);
            operationCmdCharacteristic = dcService.getCharacteristic(DC_UUID.operationCmd);
            nemeusStatusCharacteristic = dcService.getCharacteristic(DC_UUID.nemeusStatus);
            gmrStatusCharacteristic = dcService.getCharacteristic(DC_UUID.gmrStatus);
            radarStatusCharacteristic = dcService.getCharacteristic(DC_UUID.radarStatus);
            otaControlCharacteristic = otaService.getCharacteristic(DC_UUID.otaControl);

            return authCharacteristic != null &&
                    deviceIdCharacteristic != null &&
                    deviceVersionCharacteristic != null&&
                    configIdCharacteristic != null &&
                    configTransmissionIntervalCharacteristic != null &&
                    configKeepAliveIntervalCharacteristic != null &&
                    configRadioModeCharacteristic != null &&
                    configGpsCharacteristic != null &&
                    configRadarCharacteristic != null &&
                    configOperationModeCharacteristic != null &&
                    configLoRaAppEuiCharacteristic != null &&
                    configLoRaAppKeyCharacteristic != null &&
                    configLoRaDeviceEuiCharacteristic != null &&
                    operationCmdCharacteristic != null &&
                    nemeusStatusCharacteristic != null &&
                    gmrStatusCharacteristic != null &&
                    radarStatusCharacteristic != null &&
                    otaControlCharacteristic != null;
        }

        @Override
        protected Deque<Request> initGatt(BluetoothGatt gatt) {
            final LinkedList<Request> requests = new LinkedList<>();
            requests.push(Request.readRequest(deviceIdCharacteristic));
            requests.push(Request.readRequest(deviceVersionCharacteristic));
            requests.push(Request.readRequest(configIdCharacteristic));
            requests.push(Request.readRequest(configTransmissionIntervalCharacteristic));
            requests.push(Request.readRequest(configKeepAliveIntervalCharacteristic));
            requests.push(Request.readRequest(configRadioModeCharacteristic));
            requests.push(Request.readRequest(configGpsCharacteristic));
            requests.push(Request.readRequest(configRadarCharacteristic));
            requests.push(Request.readRequest(configOperationModeCharacteristic));
            requests.push(Request.readRequest(configLoRaAppEuiCharacteristic));
            requests.push(Request.readRequest(configLoRaAppKeyCharacteristic));
            requests.push(Request.readRequest(operationCmdCharacteristic));
            requests.push(Request.readRequest(configLoRaDeviceEuiCharacteristic));
            requests.push(Request.readRequest(nemeusStatusCharacteristic));
            requests.push(Request.readRequest(gmrStatusCharacteristic));
            requests.push(Request.readRequest(radarStatusCharacteristic));
            // write authentication key to characteristic
            requests.push(Request.writeRequest(authCharacteristic));
            // perform server authentication
            requests.push(Request.readRequest(authCharacteristic));
            return requests;
        }

        @Override
        protected void onDeviceDisconnected() {
            authCharacteristic = null;
            deviceIdCharacteristic = null;
            deviceVersionCharacteristic = null;
            configIdCharacteristic = null;
            configTransmissionIntervalCharacteristic = null;
            configKeepAliveIntervalCharacteristic = null;
            configRadioModeCharacteristic = null;
            configGpsCharacteristic = null;
            configRadarCharacteristic = null;
            configOperationModeCharacteristic = null;
            configLoRaAppEuiCharacteristic = null;
            configLoRaAppKeyCharacteristic = null;
            configLoRaDeviceEuiCharacteristic = null;
            nemeusStatusCharacteristic = null;
            gmrStatusCharacteristic = null;
            radarStatusCharacteristic = null;
            otaDataCharacteristic = null;
        }

        @Override
        protected void onMtuChanged(int mtu) {
            super.onMtuChanged(mtu);
            ECountBleManager.this.mtu = mtu;
        }


        @Override
        protected void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicRead(gatt, characteristic);

            if (characteristic.getUuid().equals(DC_UUID.authentication)) {
                byte encryptedData[];
                try {
                    encryptedData = BinaryUtils.encryptByteArray(characteristic.getValue());
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }
                characteristic.setValue(encryptedData);
            } else if (characteristic.getUuid().equals(DC_UUID.deviceId)) {
                deviceId = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.deviceVersion)) {
                deviceVersion = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configId)) {
                configId = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configTransmissionInterval)) {
                configTransmissionInterval = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configKeepAliveInterval)) {
                configKeepAliveInterval = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configRadioMode)) {
                configRadioMode = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configGps)) {
                configGps = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configRadar)) {
                configRadar = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configOperationMode)) {
                configOperationMode = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configLoRaAppEui)) {
                configLoRaAppEui = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configLoRaAppKey)) {
                configLoRaAppKey = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.configLoRaDeviceEui)) {
                configLoRaDeviceEui = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.nemeusStatus)) {
                nemeusStatus = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.gmrStatus)) {
                gmrStatus = characteristic.getValue();
            } else if (characteristic.getUuid().equals(DC_UUID.radarStatus)) {
                radarStatus = characteristic.getValue();
            }
        }

        @Override
        protected void onCharacteristicWrite(BluetoothGatt gatt,
                                             BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicWrite(gatt, characteristic);

            if (characteristic.getUuid().equals(DC_UUID.otaControl)) {
                final byte[] otaControl = characteristic.getValue();
                if (otaControl.length == 1) {
                    // OTA client initiates the update process
                    if (otaControl[0] == (byte) 0x00) {
                        // set OTA process flag
                        isOtaProcessing = true;

                        // check whether device is in OTA mode
                        if (isOtaMode.getValue()) {
                            // request MTU size
                            requestMtu(mtu);
                            // start update process,but ensure MTU size has been requested
                            handler.postDelayed(() -> uploadOta(), 2000);
                        } else {
                            // reconnect to establish OTA mode
                            isReconnectRequired = true;
                            // enforces device to reconnect
                            gatt.disconnect();
                        }
                    }

                    // OTA client finishes the update process
                    if (otaControl[0] == (byte) 0x03) {
                        if (isOtaProcessing) { // if device is in OTA mode and update process was successful
                            isOtaProcessing = false;
                            disconnect();
                        } else { // if device is in OTA mode, but update process was not established
                            // enforces device to reconnect
                            gatt.disconnect();
                        }
                    }
                }
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
        }
    };

    public byte[] getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(final byte[] value) {
        writeCharacteristic(deviceIdCharacteristic,
                BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT,
                value);
    }

    // Todo: implement other getters and setters

    // Here I have to get the otaAppFilePath which I discovered in OtaFragment
    public void uploadOta(final String otaAppFilePath) {
        if (otaDataCharacteristic != null) {
            otaDataCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

            byte[] ebl = null;
            try {
                FileInputStream fileInputStream = new FileInputStream(otaAppFilePath);
                int size = fileInputStream.available();
                byte[] temp = new byte[size];
                fileInputStream.read(temp);
                fileInputStream.close();
                ebl = temp;
            } catch (Exception e) {
                Logger.e(TAG, "Couldn't open file " + e);
            }
            otaAppFileStream = ebl;
            pack = 0;

            // start update process in another thread
            Thread otaUploadThread = new Thread(() -> otaWriteDataReliable());
            otaUploadThread.start();
        }
    }

    private void writeCharacteristic(final BluetoothGattCharacteristic c,
                                     final int writeType,
                                     final byte[] value) {
        if (c == null)
            return;

        c.setWriteType(writeType);
        c.setValue(value);
        writeCharacteristic(c); // will call the underlying API of BleManager
    }

}

代码涵盖了基本用例,但我仍然不确定如何将特定组件相互链接。

在阅读MVVM时,我注意到总有多种可能的解决方案/方法。我发现了以下问题:

  1. ECountBleManager是通过调用characteristics.getValue()来存储变量的正确位置吗?如果是,我是否应该将OtaFragment中发现的变量放在其中(我的意思是,我必须将mtu的值转发给ECountBleManager)?考虑一下,我必须访问我在OtaFragment中发现的变量以及其他片段。
  2. 我在哪里存储OtaFragment的变量?在ECountVieModelECountBleManager中,或者我是否创建了一个OtaViewModel(但是如何访问我已经在OtaViewModel中的ECountBleManager中创建的ECountViewModel实例?)
  3. 如何访问在ECountBleManager中的OtaFragment中发现的mtu,priority和otaAppFile?
  4. 我是否为每个活动和片段都有一个ViewModel?但是如何解决ECountBleManager实例的问题,请参阅问题2?
  5. ECountBleManager如何适应MVVM模式?我猜它是模型的一部分?!但是哪一部分呢?存储库,交互者,控制器,调解员?
  6. 代码并没有减少,所以我很抱歉,但是你看到我真的在努力,我想要变得更好。我希望有人可以帮助我解决问题并改进我的代码。提前谢谢!

0 个答案:

没有答案