DFU Starter and ListenerHelper.
This commit is contained in:
parent
c0e753a420
commit
4044524cb6
|
@ -57,16 +57,19 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.dfu.exception.DeviceDisconnectedException;
|
||||
import no.nordicsemi.android.dfu.exception.DfuException;
|
||||
import no.nordicsemi.android.dfu.exception.HexFileValidationException;
|
||||
import no.nordicsemi.android.dfu.exception.RemoteDfuException;
|
||||
import no.nordicsemi.android.dfu.exception.UnknownResponseException;
|
||||
import no.nordicsemi.android.dfu.exception.UploadAbortedException;
|
||||
import no.nordicsemi.android.dfu.scanner.BootloaderScannerFactory;
|
||||
import no.nordicsemi.android.dfu.internal.exception.DeviceDisconnectedException;
|
||||
import no.nordicsemi.android.dfu.internal.exception.DfuException;
|
||||
import no.nordicsemi.android.dfu.internal.exception.HexFileValidationException;
|
||||
import no.nordicsemi.android.dfu.internal.exception.RemoteDfuException;
|
||||
import no.nordicsemi.android.dfu.internal.exception.UnknownResponseException;
|
||||
import no.nordicsemi.android.dfu.internal.exception.UploadAbortedException;
|
||||
import no.nordicsemi.android.dfu.internal.scanner.BootloaderScannerFactory;
|
||||
import no.nordicsemi.android.dfu.internal.ArchiveInputStream;
|
||||
import no.nordicsemi.android.dfu.internal.HexInputStream;
|
||||
import no.nordicsemi.android.error.GattError;
|
||||
|
||||
/**
|
||||
|
@ -79,17 +82,17 @@ import no.nordicsemi.android.error.GattError;
|
|||
* Start the service with the following parameters:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* final Intent service = new Intent(this, YourDfuService.class);
|
||||
* service.putExtra(DfuService.EXTRA_DEVICE_ADDRESS, mSelectedDevice.getAddress()); // Target device address
|
||||
* service.putExtra(DfuService.EXTRA_DEVICE_NAME, mSelectedDevice.getName()); // This name will be shown on the notification
|
||||
* service.putExtra(DfuService.EXTRA_FILE_MIME_TYPE, mFileType == DfuService.TYPE_AUTO ? YourDfuService.MIME_TYPE_ZIP : YourDfuService.MIME_TYPE_OCTET_STREAM);
|
||||
* service.putExtra(DfuService.EXTRA_FILE_TYPE, mFileType);
|
||||
* service.putExtra(DfuService.EXTRA_FILE_PATH, mFilePath);
|
||||
* service.putExtra(DfuService.EXTRA_FILE_URI, mFileStreamUri);
|
||||
* final Intent service = new Intent(this, yourClass);
|
||||
* service.putExtra(EXTRA_DEVICE_ADDRESS, mSelectedDevice.getAddress()); // Target device address
|
||||
* service.putExtra(EXTRA_DEVICE_NAME, mSelectedDevice.getName()); // This name will be shown on the notification
|
||||
* service.putExtra(EXTRA_FILE_MIME_TYPE, mFileType == TYPE_AUTO ? YourMIME_TYPE_ZIP : YourMIME_TYPE_OCTET_STREAM);
|
||||
* service.putExtra(EXTRA_FILE_TYPE, mFileType);
|
||||
* service.putExtra(EXTRA_FILE_PATH, mFilePath);
|
||||
* service.putExtra(EXTRA_FILE_URI, mFileStreamUri);
|
||||
* // optionally
|
||||
* service.putExtra(DfuService.EXTRA_INIT_FILE_PATH, mInitFilePath);
|
||||
* service.putExtra(DfuService.EXTRA_INIT_FILE_URI, mInitFileStreamUri);
|
||||
* service.putExtra(DfuService.EXTRA_RESTORE_BOND, mRestoreBond);
|
||||
* service.putExtra(EXTRA_INIT_FILE_PATH, mInitFilePath);
|
||||
* service.putExtra(EXTRA_INIT_FILE_URI, mInitFileStreamUri);
|
||||
* service.putExtra(EXTRA_RESTORE_BOND, mRestoreBond);
|
||||
* startService(service);
|
||||
* </pre>
|
||||
* <p/>
|
||||
|
@ -144,12 +147,17 @@ public abstract class DfuBaseService extends IntentService {
|
|||
/**
|
||||
* A path to the file with the new firmware. It may point to a HEX, BIN or a ZIP file.
|
||||
* Some file manager applications return the path as a String while other return a Uri. Use the {@link #EXTRA_FILE_URI} in the later case.
|
||||
* For files included in /res/raw resource directory please use {@link #EXTRA_FILE_RES_ID} instead.
|
||||
*/
|
||||
public static final String EXTRA_FILE_PATH = "no.nordicsemi.android.dfu.extra.EXTRA_FILE_PATH";
|
||||
/**
|
||||
* See {@link #EXTRA_FILE_PATH} for details.
|
||||
*/
|
||||
public static final String EXTRA_FILE_URI = "no.nordicsemi.android.dfu.extra.EXTRA_FILE_URI";
|
||||
/**
|
||||
* See {@link #EXTRA_FILE_PATH} for details.
|
||||
*/
|
||||
public static final String EXTRA_FILE_RES_ID = "no.nordicsemi.android.dfu.extra.EXTRA_FILE_RES_ID";
|
||||
/**
|
||||
* The Init packet URI. This file is required if the Extended Init Packet is required (SDK 7.0+). Must point to a 'dat' file corresponding with the selected firmware.
|
||||
* The Init packet may contain just the CRC (in case of older versions of DFU) or the Extended Init Packet in binary format (SDK 7.0+).
|
||||
|
@ -160,6 +168,11 @@ public abstract class DfuBaseService extends IntentService {
|
|||
* The Init packet may contain just the CRC (in case of older versions of DFU) or the Extended Init Packet in binary format (SDK 7.0+).
|
||||
*/
|
||||
public static final String EXTRA_INIT_FILE_URI = "no.nordicsemi.android.dfu.extra.EXTRA_INIT_FILE_URI";
|
||||
/**
|
||||
* The Init packet URI. This file is required if the Extended Init Packet is required (SDK 7.0+). Must point to a 'dat' file corresponding with the selected firmware.
|
||||
* The Init packet may contain just the CRC (in case of older versions of DFU) or the Extended Init Packet in binary format (SDK 7.0+).
|
||||
*/
|
||||
public static final String EXTRA_INIT_FILE_RES_ID = "no.nordicsemi.android.dfu.extra.EXTRA_INIT_FILE_RES_ID";
|
||||
/**
|
||||
* The input file mime-type. Currently only "application/zip" (ZIP) or "application/octet-stream" (HEX or BIN) are supported. If this parameter is
|
||||
* empty the "application/octet-stream" is assumed.
|
||||
|
@ -611,14 +624,15 @@ public abstract class DfuBaseService extends IntentService {
|
|||
private boolean mRequestCompleted;
|
||||
/**
|
||||
* <p>
|
||||
* Flag set to <code>true</code> when the DFU target had send any notification with status other than {@link #DFU_STATUS_SUCCESS}. Setting it to <code>true</code> will abort sending firmware and
|
||||
* Flag set to <code>true</code> when the DFU target had send a notification with status other than {@link #DFU_STATUS_SUCCESS}. Setting it to <code>true</code> will abort sending firmware and
|
||||
* stop logging notifications (read below for explanation).
|
||||
* </p>
|
||||
* <p>
|
||||
* The onCharacteristicWrite(..) callback is written when Android puts the packet to the outgoing queue, not when it physically send the data. Therefore, in case of invalid state of the DFU
|
||||
* target, Android will first put up to N* packets, one by one, while in fact the first will be transmitted. In case the DFU target is in an invalid state it will notify Android with a
|
||||
* notification 10-03-02 for each packet of firmware that has been sent. However, just after receiving the first one this service will try to send the reset command while still getting more
|
||||
* 10-03-02 notifications. This flag will prevent from logging "Notification received..." more than once.
|
||||
* The onCharacteristicWrite(..) callback is called when Android writes the packet into the outgoing queue, not when it physically sends the data.
|
||||
* This means that the service will first put up to N* packets, one by one, to the queue, while in fact the first one is transmitted.
|
||||
* In case the DFU target is in an invalid state it will notify Android with a notification 10-03-02 for each packet of firmware that has been sent.
|
||||
* After receiving the first such notification, the DFU service will add the reset command to the outgoing queue, but it will still be receiving such notifications
|
||||
* until all the data packets are sent. Those notifications should be ignored. This flag will prevent from logging "Notification received..." more than once.
|
||||
* </p>
|
||||
* <p>
|
||||
* Additionally, sometimes after writing the command 6 ({@link #OP_CODE_RESET}), Android will receive a notification and update the characteristic value with 10-03-02 and the callback for write
|
||||
|
@ -629,7 +643,9 @@ public abstract class DfuBaseService extends IntentService {
|
|||
* </p>
|
||||
*/
|
||||
private boolean mRemoteErrorOccurred;
|
||||
/** Flag set to true if sending was paused. */
|
||||
private boolean mPaused;
|
||||
/** Flag set to true if sending was aborted. */
|
||||
private boolean mAborted;
|
||||
/**
|
||||
* Latest data received from device using notification.
|
||||
|
@ -1069,8 +1085,10 @@ public abstract class DfuBaseService extends IntentService {
|
|||
final String deviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
|
||||
final String filePath = intent.getStringExtra(EXTRA_FILE_PATH);
|
||||
final Uri fileUri = intent.getParcelableExtra(EXTRA_FILE_URI);
|
||||
final int fileResId = intent.getIntExtra(EXTRA_FILE_RES_ID, 0);
|
||||
final String initFilePath = intent.getStringExtra(EXTRA_INIT_FILE_PATH);
|
||||
final Uri initFileUri = intent.getParcelableExtra(EXTRA_INIT_FILE_URI);
|
||||
final int initFileResId = intent.getIntExtra(EXTRA_INIT_FILE_RES_ID, 0);
|
||||
int fileType = intent.getIntExtra(EXTRA_FILE_TYPE, TYPE_AUTO);
|
||||
if (filePath != null && fileType == TYPE_AUTO)
|
||||
fileType = filePath.toLowerCase(Locale.US).endsWith("zip") ? TYPE_AUTO : TYPE_APPLICATION;
|
||||
|
@ -1149,8 +1167,10 @@ public abstract class DfuBaseService extends IntentService {
|
|||
sendLogBroadcast(LOG_LEVEL_VERBOSE, "Opening file...");
|
||||
if (fileUri != null) {
|
||||
is = openInputStream(fileUri, mimeType, mbrSize, fileType);
|
||||
} else {
|
||||
} else if (filePath != null) {
|
||||
is = openInputStream(filePath, mimeType, mbrSize, fileType);
|
||||
} else if (fileResId > 0) {
|
||||
is = openInputStream(fileResId, mimeType, mbrSize, fileType);
|
||||
}
|
||||
|
||||
if (initFileUri != null) {
|
||||
|
@ -1159,6 +1179,9 @@ public abstract class DfuBaseService extends IntentService {
|
|||
} else if (initFilePath != null) {
|
||||
// Try to read the Init Packet file from path
|
||||
initIs = new FileInputStream(initFilePath);
|
||||
} else if (initFileResId > 0) {
|
||||
// Try to read the Init Packet file from given resource
|
||||
initIs = getResources().openRawResource(initFileResId);
|
||||
}
|
||||
|
||||
mInputStream = is;
|
||||
|
@ -1865,7 +1888,7 @@ public abstract class DfuBaseService extends IntentService {
|
|||
/**
|
||||
* Opens the binary input stream that returns the firmware image content. A Path to the file is given.
|
||||
*
|
||||
* @param filePath the path to the HEX or BIN file
|
||||
* @param filePath the path to the HEX, BIN or ZIP file
|
||||
* @param mimeType the file type
|
||||
* @param mbrSize the size of MBR, by default 0x1000
|
||||
* @param types the content files types in ZIP
|
||||
|
@ -1909,6 +1932,27 @@ public abstract class DfuBaseService extends IntentService {
|
|||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the binary input stream that returns the firmware image content. A resource id in the res/raw is given.
|
||||
*
|
||||
* @param resId the if of the resource file
|
||||
* @param mimeType the file type
|
||||
* @param mbrSize the size of MBR, by default 0x1000
|
||||
* @param types the content files types in ZIP
|
||||
* @return the input stream with binary image content
|
||||
*/
|
||||
private InputStream openInputStream(final int resId, final String mimeType, final int mbrSize, final int types) throws IOException {
|
||||
final InputStream is = getResources().openRawResource(resId);
|
||||
if (MIME_TYPE_ZIP.equals(mimeType))
|
||||
return new ArchiveInputStream(is, mbrSize, types);
|
||||
is.mark(2);
|
||||
int firstByte = is.read();
|
||||
is.reset();
|
||||
if (firstByte == ':')
|
||||
return new HexInputStream(is, mbrSize);
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the BLE device with given address. This method is SYNCHRONOUS, it wait until the connection status change from {@link #STATE_CONNECTING} to {@link #STATE_CONNECTED_AND_READY} or an
|
||||
* error occurs. This method returns <code>null</code> if Bluetooth adapter is disabled.
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*************************************************************************************************************************************************
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
|
||||
public interface DfuLogListener {
|
||||
/**
|
||||
* Method called when a log event was sent from the DFU service.
|
||||
* @param deviceAddress the target device address
|
||||
* @param level the log level, one of:
|
||||
* <ul>
|
||||
* <li>{@link DfuBaseService#LOG_LEVEL_DEBUG}</li>
|
||||
* <li>{@link DfuBaseService#LOG_LEVEL_VERBOSE}</li>
|
||||
* <li>{@link DfuBaseService#LOG_LEVEL_INFO}</li>
|
||||
* <li>{@link DfuBaseService#LOG_LEVEL_APPLICATION}</li>
|
||||
* <li>{@link DfuBaseService#LOG_LEVEL_WARNING}</li>
|
||||
* <li>{@link DfuBaseService#LOG_LEVEL_ERROR}</li>
|
||||
* </ul>
|
||||
* @param message the log message
|
||||
*/
|
||||
public void onLogEvent(final String deviceAddress, final int level, final String message);
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*************************************************************************************************************************************************
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
|
||||
public interface DfuProgressListener {
|
||||
|
||||
/**
|
||||
* Method called when the DFU service started connecting with the DFU target.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDeviceConnecting(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the service has successfully connected, discovered services and found DFU service on the DFU target.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDeviceConnected(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the DFU process is starting. This includes reading the DFU Version characteristic, sending DFU_START command as well as the Init packet, if set.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDfuProcessStarting(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the DFU process was started and bytes about to be sent.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDfuProcessStarted(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the service discovered that the DFU target is in the application mode and must be switched to DFU mode.
|
||||
* The switch command will be sent and the DFU process should start again. There will be no {@link #onDeviceDisconnected(String)} event following this call.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onEnablingDfuMode(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called during uploading the firmware. It will not be called twice with the same value of percent, however, in case of small firmware files, some values may be omitted.
|
||||
* @param deviceAddress the target device address
|
||||
* @param percent the current status of upload (0-99)
|
||||
* @param speed the current speed in bytes per millisecond
|
||||
* @param avgSpeed the average speed in bytes per millisecond
|
||||
* @param currentPart the number pf part being sent. In case the ZIP file contains a Soft Device and/or a Bootloader together with the application the SD+BL are sent as part 1,
|
||||
* then the service starts again and send the application as part 2
|
||||
* @param partsTotal total number of parts
|
||||
*/
|
||||
public void onProgressChanged(final String deviceAddress, final int percent, final float speed, final float avgSpeed, final int currentPart, final int partsTotal);
|
||||
|
||||
/**
|
||||
* Method called when the new firmware is being validated on the target device.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onFirmwareValidating(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the service started to disconnect from the target device.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDeviceDisconnecting(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the service disconnected from the device. The device has been reset.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDeviceDisconnected(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the DFU process succeeded.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDfuCompleted(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when the DFU process has been aborted.
|
||||
* @param deviceAddress the target device address
|
||||
*/
|
||||
public void onDfuAborted(final String deviceAddress);
|
||||
|
||||
/**
|
||||
* Method called when an error occur.
|
||||
* @param deviceAddress the target device address
|
||||
* @param error error number
|
||||
* @param errorType the error type, one of {@link DfuBaseService#ERROR_TYPE_COMMUNICATION_STATE}, {@link DfuBaseService#ERROR_TYPE_COMMUNICATION},
|
||||
* {@link DfuBaseService#ERROR_TYPE_DFU_REMOTE}, {@link DfuBaseService#ERROR_TYPE_OTHER}.
|
||||
* @param message the error message
|
||||
*/
|
||||
public void onError(final String deviceAddress, final int error, final int errorType, final String message);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*************************************************************************************************************************************************
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
|
||||
public class DfuProgressListenerAdapter implements DfuProgressListener {
|
||||
@Override
|
||||
public void onDeviceConnecting(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuProcessStarting(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuProcessStarted(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnablingDfuMode(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(final String deviceAddress, final int percent, final float speed, final float avgSpeed, final int currentPart, final int partsTotal) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirmwareValidating(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuCompleted(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuAborted(final String deviceAddress) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String deviceAddress, final int error, final int errorType, final String message) {
|
||||
// empty default implementation
|
||||
}
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
/*************************************************************************************************************************************************
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import no.nordicsemi.android.error.GattError;
|
||||
|
||||
public class DfuServiceListenerHelper {
|
||||
private static LogBroadcastReceiver mLogBroadcastReceiver;
|
||||
private static ProgressBroadcastsReceiver mProgressBroadcastReceiver;
|
||||
|
||||
private static class LogBroadcastReceiver extends BroadcastReceiver {
|
||||
private DfuLogListener mGlobalLogListener;
|
||||
private Map<String, DfuLogListener> mListeners = new HashMap<>();
|
||||
|
||||
private void setLogListener(final DfuLogListener globalLogListener) {
|
||||
this.mGlobalLogListener = globalLogListener;
|
||||
}
|
||||
|
||||
private void setLogListener(final String deviceAddress, final DfuLogListener listener) {
|
||||
mListeners.put(deviceAddress, listener);
|
||||
}
|
||||
|
||||
private boolean removeLogListener(final DfuLogListener listener) {
|
||||
if (mGlobalLogListener == listener)
|
||||
mGlobalLogListener = null;
|
||||
|
||||
for (final Map.Entry<String, DfuLogListener> entry : mListeners.entrySet()) {
|
||||
if (entry.getValue() == listener) {
|
||||
mListeners.remove(entry.getKey());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mGlobalLogListener == null && mListeners.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String address = intent.getStringExtra(DfuBaseService.EXTRA_DEVICE_ADDRESS);
|
||||
|
||||
// Find proper listeners
|
||||
final DfuLogListener globalListener = mGlobalLogListener;
|
||||
final DfuLogListener deviceListener = mListeners.get(address);
|
||||
|
||||
if (globalListener == null && deviceListener == null)
|
||||
return;
|
||||
|
||||
final int level = intent.getIntExtra(DfuBaseService.EXTRA_LOG_LEVEL, 0);
|
||||
final String message = intent.getStringExtra(DfuBaseService.EXTRA_LOG_MESSAGE);
|
||||
|
||||
if (globalListener != null)
|
||||
globalListener.onLogEvent(address, level, message);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onLogEvent(address, level, message);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProgressBroadcastsReceiver extends BroadcastReceiver {
|
||||
private DfuProgressListener mGlobalProgressListener;
|
||||
private Map<String, DfuProgressListener> mListeners = new HashMap<>();
|
||||
|
||||
private void setProgressListener(final DfuProgressListener globalProgressListener) {
|
||||
this.mGlobalProgressListener = globalProgressListener;
|
||||
}
|
||||
|
||||
private void setProgressListener(final String deviceAddress, final DfuProgressListener listener) {
|
||||
mListeners.put(deviceAddress, listener);
|
||||
}
|
||||
|
||||
private boolean removeProgressListener(final DfuProgressListener listener) {
|
||||
if (mGlobalProgressListener == listener)
|
||||
mGlobalProgressListener = null;
|
||||
|
||||
for (final Map.Entry<String, DfuProgressListener> entry : mListeners.entrySet()) {
|
||||
if (entry.getValue() == listener) {
|
||||
mListeners.remove(entry.getKey());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mGlobalProgressListener == null && mListeners.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String address = intent.getStringExtra(DfuBaseService.EXTRA_DEVICE_ADDRESS);
|
||||
|
||||
// Find proper listeners
|
||||
final DfuProgressListener globalListener = mGlobalProgressListener;
|
||||
final DfuProgressListener deviceListener = mListeners.get(address);
|
||||
|
||||
if (globalListener == null && deviceListener == null)
|
||||
return;
|
||||
|
||||
final String action = intent.getAction();
|
||||
|
||||
switch (action) {
|
||||
case DfuBaseService.BROADCAST_PROGRESS: {
|
||||
final int progress = intent.getIntExtra(DfuBaseService.EXTRA_DATA, 0);
|
||||
final float speed = intent.getFloatExtra(DfuBaseService.EXTRA_SPEED_B_PER_MS, 0.0f);
|
||||
final float avgSpeed = intent.getFloatExtra(DfuBaseService.EXTRA_AVG_SPEED_B_PER_MS, 0.0f);
|
||||
final int currentPart = intent.getIntExtra(DfuBaseService.EXTRA_PART_CURRENT, 0);
|
||||
final int partsTotal = intent.getIntExtra(DfuBaseService.EXTRA_PARTS_TOTAL, 0);
|
||||
|
||||
switch (progress) {
|
||||
case DfuBaseService.PROGRESS_CONNECTING:
|
||||
if (globalListener != null)
|
||||
globalListener.onDeviceConnecting(address);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onDeviceConnecting(address);
|
||||
break;
|
||||
case DfuBaseService.PROGRESS_STARTING:
|
||||
if (globalListener != null) {
|
||||
globalListener.onDeviceConnected(address);
|
||||
globalListener.onDfuProcessStarting(address);
|
||||
}
|
||||
if (deviceListener != null) {
|
||||
deviceListener.onDeviceConnected(address);
|
||||
deviceListener.onDfuProcessStarting(address);
|
||||
}
|
||||
break;
|
||||
case DfuBaseService.PROGRESS_ENABLING_DFU_MODE:
|
||||
if (globalListener != null)
|
||||
globalListener.onEnablingDfuMode(address);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onEnablingDfuMode(address);
|
||||
break;
|
||||
case DfuBaseService.PROGRESS_VALIDATING:
|
||||
if (globalListener != null)
|
||||
globalListener.onFirmwareValidating(address);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onFirmwareValidating(address);
|
||||
break;
|
||||
case DfuBaseService.PROGRESS_DISCONNECTING:
|
||||
if (globalListener != null)
|
||||
globalListener.onDeviceDisconnecting(address);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onDeviceDisconnecting(address);
|
||||
break;
|
||||
case DfuBaseService.PROGRESS_COMPLETED:
|
||||
if (globalListener != null) {
|
||||
globalListener.onDeviceDisconnected(address);
|
||||
globalListener.onDfuCompleted(address);
|
||||
}
|
||||
if (deviceListener != null) {
|
||||
deviceListener.onDeviceDisconnected(address);
|
||||
deviceListener.onDfuCompleted(address);
|
||||
}
|
||||
break;
|
||||
case DfuBaseService.PROGRESS_ABORTED:
|
||||
if (globalListener != null) {
|
||||
globalListener.onDeviceDisconnected(address);
|
||||
globalListener.onDfuAborted(address);
|
||||
}
|
||||
if (deviceListener != null) {
|
||||
deviceListener.onDeviceDisconnected(address);
|
||||
deviceListener.onDfuAborted(address);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (progress == 0) {
|
||||
if (globalListener != null)
|
||||
globalListener.onDfuProcessStarted(address);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onDfuProcessStarted(address);
|
||||
}
|
||||
if (globalListener != null)
|
||||
globalListener.onProgressChanged(address, progress, speed, avgSpeed, currentPart, partsTotal);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onProgressChanged(address, progress, speed, avgSpeed, currentPart, partsTotal);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case DfuBaseService.BROADCAST_ERROR: {
|
||||
final int error = intent.getIntExtra(DfuBaseService.EXTRA_DATA, 0);
|
||||
final int errorType = intent.getIntExtra(DfuBaseService.EXTRA_ERROR_TYPE, 0);
|
||||
|
||||
if (globalListener != null)
|
||||
globalListener.onDeviceDisconnected(address);
|
||||
if (deviceListener != null)
|
||||
deviceListener.onDeviceDisconnected(address);
|
||||
switch (errorType) {
|
||||
case DfuBaseService.ERROR_TYPE_COMMUNICATION_STATE:
|
||||
if (globalListener != null)
|
||||
globalListener.onError(address, error, errorType, GattError.parseConnectionError(error));
|
||||
if (deviceListener != null)
|
||||
deviceListener.onError(address, error, errorType, GattError.parseConnectionError(error));
|
||||
break;
|
||||
default:
|
||||
if (globalListener != null)
|
||||
globalListener.onError(address, error, errorType, GattError.parse(error));
|
||||
if (deviceListener != null)
|
||||
deviceListener.onError(address, error, errorType, GattError.parse(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the {@link DfuProgressListener}. Registered listener will receive the progress events from the DFU service.
|
||||
* @param context the application context
|
||||
* @param listener the listener to register
|
||||
*/
|
||||
public static void registerProgressListener(final Context context, final DfuProgressListener listener) {
|
||||
if (mProgressBroadcastReceiver == null) {
|
||||
mProgressBroadcastReceiver = new ProgressBroadcastsReceiver();
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(DfuBaseService.BROADCAST_PROGRESS);
|
||||
filter.addAction(DfuBaseService.BROADCAST_ERROR);
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(mProgressBroadcastReceiver, filter);
|
||||
}
|
||||
mProgressBroadcastReceiver.setProgressListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the {@link DfuProgressListener}. Registered listener will receive the progress events from the DFU service.
|
||||
* @param context the application context
|
||||
* @param listener the listener to register
|
||||
* @param deviceAddress the address of the device to receive updates from (or null if any device)
|
||||
*/
|
||||
public static void registerProgressListener(final Context context, final DfuProgressListener listener, final String deviceAddress) {
|
||||
if (mProgressBroadcastReceiver == null) {
|
||||
mProgressBroadcastReceiver = new ProgressBroadcastsReceiver();
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(DfuBaseService.BROADCAST_PROGRESS);
|
||||
filter.addAction(DfuBaseService.BROADCAST_ERROR);
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(mProgressBroadcastReceiver, filter);
|
||||
}
|
||||
mProgressBroadcastReceiver.setProgressListener(deviceAddress, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the previously registered progress listener.
|
||||
* @param context the application context
|
||||
* @param listener the listener to unregister
|
||||
*/
|
||||
public static void unregisterProgressListener(final Context context, final DfuProgressListener listener) {
|
||||
if (mProgressBroadcastReceiver != null) {
|
||||
final boolean empty = mProgressBroadcastReceiver.removeProgressListener(listener);
|
||||
|
||||
if (empty) {
|
||||
LocalBroadcastManager.getInstance(context).unregisterReceiver(mProgressBroadcastReceiver);
|
||||
mProgressBroadcastReceiver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the {@link DfuLogListener}. Registered listener will receive the log events from the DFU service.
|
||||
* @param context the application context
|
||||
* @param listener the listener to register
|
||||
*/
|
||||
public static void registerLogListener(final Context context, final DfuLogListener listener) {
|
||||
if (mLogBroadcastReceiver == null) {
|
||||
mLogBroadcastReceiver = new LogBroadcastReceiver();
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(DfuBaseService.BROADCAST_LOG);
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(mLogBroadcastReceiver, filter);
|
||||
}
|
||||
mLogBroadcastReceiver.setLogListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the {@link DfuLogListener}. Registered listener will receive the log events from the DFU service.
|
||||
* @param context the application context
|
||||
* @param listener the listener to register
|
||||
* @param deviceAddress the address of the device to receive updates from (or null if any device)
|
||||
*/
|
||||
public static void registerLogListener(final Context context, final DfuLogListener listener, final String deviceAddress) {
|
||||
if (mLogBroadcastReceiver == null) {
|
||||
mLogBroadcastReceiver = new LogBroadcastReceiver();
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(DfuBaseService.BROADCAST_LOG);
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(mLogBroadcastReceiver, filter);
|
||||
}
|
||||
mLogBroadcastReceiver.setLogListener(deviceAddress, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the previously registered log listener.
|
||||
* @param context the application context
|
||||
* @param listener the listener to unregister
|
||||
*/
|
||||
public static void unregisterLogListener(final Context context, final DfuLogListener listener) {
|
||||
if (mLogBroadcastReceiver != null) {
|
||||
final boolean empty = mLogBroadcastReceiver.removeLogListener(listener);
|
||||
|
||||
if (empty) {
|
||||
LocalBroadcastManager.getInstance(context).unregisterReceiver(mLogBroadcastReceiver);
|
||||
mLogBroadcastReceiver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
/**
|
||||
* **********************************************************************************************************************************************
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
* <p/>
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
* <p/>
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* <p/>
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* <p/>
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
* <p/>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* **********************************************************************************************************************************************
|
||||
*/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
|
||||
/**
|
||||
* Starting the DfuService service requires a knowledge of some EXTRA_* constants used to pass parameters to the service.
|
||||
* The DfuServiceStater class may be used to make this process easier. It provides simple API that covers all low lever operations.
|
||||
*/
|
||||
public class DfuServiceStarter {
|
||||
private final String deviceAddress;
|
||||
private String deviceName;
|
||||
|
||||
private Uri fileUri;
|
||||
private String filePath;
|
||||
private int fileResId;
|
||||
|
||||
private Uri initFileUri;
|
||||
private String initFilePath;
|
||||
private int initFileResId;
|
||||
|
||||
private String mimeType;
|
||||
private int fileType = -1;
|
||||
|
||||
private boolean keepBond;
|
||||
|
||||
/**
|
||||
* Creates the builder. Use setZip(...), or setBinOrHex(...) methods to specify the file you want to upload.
|
||||
* In the latter case an init file may also be set using the setInitFile(...) method. Init files are required by DFU Bootloader version 0.5 or newer (SDK 7.0.0+).
|
||||
* @param deviceAddress the target device device address
|
||||
*/
|
||||
public DfuServiceStarter(final String deviceAddress) {
|
||||
this.deviceAddress = deviceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the device name. The device name is not required. It's written in the notification during the DFU process.
|
||||
* If not set the {@link no.nordicsemi.android.dfu.R.string#dfu_unknown_name R.string.dfu_unknown_name} value will be used.
|
||||
* @param name the device name (optional)
|
||||
* @return the builder
|
||||
*/
|
||||
public DfuServiceStarter setDeviceName(final String name) {
|
||||
this.deviceName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the bond information should be preserver after flashing new application. This feature requires DFU Bootloader version 0.6 or newer (SDK 8.0.0+).
|
||||
* Please see the {@link DfuBaseService#EXTRA_KEEP_BOND} for more information regarding requirements. Remember that currently updating the Soft Device will remove the bond information.
|
||||
* @param keepBond whether the bond information should be preserved in the new application.
|
||||
* @return the builder
|
||||
*/
|
||||
public DfuServiceStarter setKeepBond(final boolean keepBond) {
|
||||
this.keepBond = keepBond;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI to the Distribution packet (ZIP) or to a ZIP file matching the deprecated naming convention.
|
||||
* @param fileType the file type, a bit field created from:
|
||||
* <ul>
|
||||
* <li>{@link DfuBaseService#TYPE_APPLICATION} - the Application will be sent</li>
|
||||
* <li>{@link DfuBaseService#TYPE_SOFT_DEVICE} - he Soft Device will be sent</li>
|
||||
* <li>{@link DfuBaseService#TYPE_BOOTLOADER} - the Bootloader will be sent</li>
|
||||
* </ul>
|
||||
* or {@link DfuBaseService#TYPE_AUTO} - a type will be automatically selected based on the ZIP content
|
||||
* @param uri the URI of the file
|
||||
* @return the builder
|
||||
* @see #setZip(int, String)
|
||||
* @see #setZip(int, int)
|
||||
*/
|
||||
public DfuServiceStarter setZip(final int fileType, final Uri uri) {
|
||||
return init(uri, null, 0, fileType, DfuBaseService.MIME_TYPE_ZIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the Distribution packet (ZIP) or the a ZIP file matching the deprecated naming convention.
|
||||
* @param fileType see {@link #setZip(int, Uri)} for details
|
||||
* @param path path to the file
|
||||
* @return the builder
|
||||
* @see #setZip(int, Uri)
|
||||
* @see #setZip(int, int)
|
||||
*/
|
||||
public DfuServiceStarter setZip(final int fileType, final String path) {
|
||||
return init(null, path, 0, fileType, DfuBaseService.MIME_TYPE_ZIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resource ID of the Distribution packet (ZIP) or the a ZIP file matching the deprecated naming convention. The file should be in the /res/raw folder.
|
||||
* @param fileType see {@link #setZip(int, Uri)} for details
|
||||
* @param rawResId file's resource ID
|
||||
* @return the builder
|
||||
* @see #setZip(int, Uri)
|
||||
* @see #setZip(int, String)
|
||||
*/
|
||||
public DfuServiceStarter setZip(final int fileType, final int rawResId) {
|
||||
return init(null, null, rawResId, fileType, DfuBaseService.MIME_TYPE_ZIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI or path of the ZIP file. If the URI and path are not null the URI will be used.
|
||||
* @param fileType see {@link #setZip(int, Uri)} for details
|
||||
* @param uri the URI of the file
|
||||
* @param path the path of the file
|
||||
* @return the builder
|
||||
*/
|
||||
public DfuServiceStarter setZip(final int fileType, final Uri uri, final String path) {
|
||||
return init(uri, path, 0, fileType, DfuBaseService.MIME_TYPE_ZIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI of the BIN or HEX file containing the new firmware.
|
||||
* For DFU Bootloader version 0.5 or newer the init file must be specified using one of {@link #setInitFile(Uri)} methods.
|
||||
* @param fileType the file type, a bit field created from:
|
||||
* <ul>
|
||||
* <li>{@link DfuBaseService#TYPE_APPLICATION} - the Application will be sent</li>
|
||||
* <li>{@link DfuBaseService#TYPE_SOFT_DEVICE} - he Soft Device will be sent</li>
|
||||
* <li>{@link DfuBaseService#TYPE_BOOTLOADER} - the Bootloader will be sent</li>
|
||||
* </ul>
|
||||
* @param uri the URI of the file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setBinOrHex(final int fileType, final Uri uri) {
|
||||
if (fileType == DfuBaseService.TYPE_AUTO)
|
||||
throw new UnsupportedOperationException("You must specify the file type");
|
||||
return init(uri, null, 0, fileType, DfuBaseService.MIME_TYPE_OCTET_STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI of the BIN or HEX file containing the new firmware.
|
||||
* For DFU Bootloader version 0.5 or newer the init file must be specified using one of {@link #setInitFile(String)} methods.
|
||||
* @param fileType see {@link #setBinOrHex(int, Uri)} for details
|
||||
* @param path path to the file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setBinOrHex(final int fileType, final String path) {
|
||||
if (fileType == DfuBaseService.TYPE_AUTO)
|
||||
throw new UnsupportedOperationException("You must specify the file type");
|
||||
return init(null, path, 0, fileType, DfuBaseService.MIME_TYPE_OCTET_STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI or path to the BIN or HEX file containing the new firmware.
|
||||
* For DFU Bootloader version 0.5 or newer the init file must be specified using one of {@link #setInitFile(String)} methods.
|
||||
* @param fileType see {@link #setBinOrHex(int, Uri)} for details
|
||||
* @param uri the URI of the file
|
||||
* @param path path to the file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setBinOrHex(final int fileType, final Uri uri, final String path) {
|
||||
if (fileType == DfuBaseService.TYPE_AUTO)
|
||||
throw new UnsupportedOperationException("You must specify the file type");
|
||||
return init(null, path, 0, fileType, DfuBaseService.MIME_TYPE_OCTET_STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resource ID pointing the BIN or HEX file containing the new firmware. The file should be in the /res/raw folder.
|
||||
* For DFU Bootloader version 0.5 or newer the init file must be specified using one of {@link #setInitFile(int)} methods.
|
||||
* @param fileType see {@link #setBinOrHex(int, Uri)} for details
|
||||
* @param rawResId resource ID
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setBinOrHex(final int fileType, final int rawResId) {
|
||||
if (fileType == DfuBaseService.TYPE_AUTO)
|
||||
throw new UnsupportedOperationException("You must specify the file type");
|
||||
return init(null, null, rawResId, fileType, DfuBaseService.MIME_TYPE_OCTET_STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI of the Init file. The init file for DFU Bootloader version pre-0.5 (SDK 4.3, 6.0, 6.1) contains only the CRC-16 of the firmware.
|
||||
* Bootloader version 0.5 or newer requires the Extended Init Packet.
|
||||
* @param initFileUri the URI of the init file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setInitFile(final Uri initFileUri) {
|
||||
return init(initFileUri, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the Init file. The init file for DFU Bootloader version pre-0.5 (SDK 4.3, 6.0, 6.1) contains only the CRC-16 of the firmware.
|
||||
* Bootloader version 0.5 or newer requires the Extended Init Packet.
|
||||
* @param initFilePath the path to the init file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setInitFile(final String initFilePath) {
|
||||
return init(null, initFilePath, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resource ID of the Init file. The init file for DFU Bootloader version pre-0.5 (SDK 4.3, 6.0, 6.1) contains only the CRC-16 of the firmware.
|
||||
* Bootloader version 0.5 or newer requires the Extended Init Packet.
|
||||
* @param initFileResId the resource ID of the init file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setInitFile(final int initFileResId) {
|
||||
return init(null, null, initFileResId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URI or path to the Init file. The init file for DFU Bootloader version pre-0.5 (SDK 4.3, 6.0, 6.1) contains only the CRC-16 of the firmware.
|
||||
* Bootloader version 0.5 or newer requires the Extended Init Packet. If the URI and path are not null the URI will be used.
|
||||
* @param initFileUri the URI of the init file
|
||||
* @return the builder
|
||||
*/
|
||||
@Deprecated
|
||||
public DfuServiceStarter setInitFile(final Uri initFileUri, final String initFilePath) {
|
||||
return init(initFileUri, initFilePath, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the DFU service.
|
||||
* @param context the application context
|
||||
* @param service the class derived from the BaseDfuService
|
||||
*/
|
||||
public void start(final Context context, final Class<? extends DfuBaseService> service) {
|
||||
if (fileType == -1)
|
||||
throw new UnsupportedOperationException("You must specify the firmware file before starting the service");
|
||||
|
||||
final Intent intent = new Intent(context, service);
|
||||
|
||||
intent.putExtra(DfuBaseService.EXTRA_DEVICE_ADDRESS, deviceAddress);
|
||||
intent.putExtra(DfuBaseService.EXTRA_DEVICE_NAME, deviceName);
|
||||
intent.putExtra(DfuBaseService.EXTRA_FILE_MIME_TYPE, mimeType);
|
||||
intent.putExtra(DfuBaseService.EXTRA_FILE_TYPE, fileType);
|
||||
intent.putExtra(DfuBaseService.EXTRA_FILE_URI, fileUri);
|
||||
intent.putExtra(DfuBaseService.EXTRA_FILE_PATH, filePath);
|
||||
intent.putExtra(DfuBaseService.EXTRA_FILE_RES_ID, fileResId);
|
||||
intent.putExtra(DfuBaseService.EXTRA_INIT_FILE_URI, initFileUri);
|
||||
intent.putExtra(DfuBaseService.EXTRA_INIT_FILE_PATH, initFilePath);
|
||||
intent.putExtra(DfuBaseService.EXTRA_INIT_FILE_RES_ID, initFileResId);
|
||||
intent.putExtra(DfuBaseService.EXTRA_KEEP_BOND, keepBond);
|
||||
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
private DfuServiceStarter init(final Uri initFileUri, final String initFilePath, final int initFileResId) {
|
||||
if (DfuBaseService.MIME_TYPE_ZIP.equals(mimeType))
|
||||
throw new InvalidParameterException("Init file must be located inside the ZIP");
|
||||
|
||||
this.initFileUri = initFileUri;
|
||||
this.initFilePath = initFilePath;
|
||||
this.initFileResId = initFileResId;
|
||||
return this;
|
||||
}
|
||||
|
||||
private DfuServiceStarter init(final Uri fileUri, final String filePath, final int fileResId, final int fileType, final String mimeType) {
|
||||
this.fileUri = fileUri;
|
||||
this.filePath = filePath;
|
||||
this.fileResId = fileResId;
|
||||
this.fileType = fileType;
|
||||
this.mimeType = mimeType;
|
||||
|
||||
// If the MIME TYPE implies it's a ZIP file then the init file must be included in the file.
|
||||
if (DfuBaseService.MIME_TYPE_ZIP.equals(mimeType)) {
|
||||
this.initFileUri = null;
|
||||
this.initFilePath = null;
|
||||
this.initFileResId = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
package no.nordicsemi.android.dfu.internal;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
@ -33,10 +33,11 @@ import java.util.Map;
|
|||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import no.nordicsemi.android.dfu.manifest.FileInfo;
|
||||
import no.nordicsemi.android.dfu.manifest.Manifest;
|
||||
import no.nordicsemi.android.dfu.manifest.ManifestFile;
|
||||
import no.nordicsemi.android.dfu.manifest.SoftDeviceBootloaderFileInfo;
|
||||
import no.nordicsemi.android.dfu.DfuBaseService;
|
||||
import no.nordicsemi.android.dfu.internal.manifest.FileInfo;
|
||||
import no.nordicsemi.android.dfu.internal.manifest.Manifest;
|
||||
import no.nordicsemi.android.dfu.internal.manifest.ManifestFile;
|
||||
import no.nordicsemi.android.dfu.internal.manifest.SoftDeviceBootloaderFileInfo;
|
||||
|
||||
/**
|
||||
* <p>Reads the firmware files from the a ZIP file. The ZIP file must be either created using the <b>nrf utility</b> tool, available together with Master Control Panel v3.8.0+,
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu;
|
||||
package no.nordicsemi.android.dfu.internal;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -28,7 +28,7 @@ import java.io.FilterInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import no.nordicsemi.android.dfu.exception.HexFileValidationException;
|
||||
import no.nordicsemi.android.dfu.internal.exception.HexFileValidationException;
|
||||
|
||||
/**
|
||||
* Reads the binary content from the HEX file using IntelHex standard: http://www.interlog.com/~speff/usefulinfo/Hexfrmt.pdf.
|
||||
|
@ -61,7 +61,7 @@ public class HexInputStream extends FilterInputStream {
|
|||
* @throws java.io.IOException
|
||||
* if the stream is closed or another IOException occurs.
|
||||
*/
|
||||
protected HexInputStream(final InputStream in, final int mbrSize) throws HexFileValidationException, IOException {
|
||||
public HexInputStream(final InputStream in, final int mbrSize) throws HexFileValidationException, IOException {
|
||||
super(new BufferedInputStream(in));
|
||||
this.localBuf = new byte[LINE_LENGTH];
|
||||
this.localPos = LINE_LENGTH; // we are at the end of the local buffer, new one must be obtained
|
||||
|
@ -72,7 +72,7 @@ public class HexInputStream extends FilterInputStream {
|
|||
this.available = calculateBinSize(mbrSize);
|
||||
}
|
||||
|
||||
protected HexInputStream(final byte[] data, final int mbrSize) throws HexFileValidationException, IOException {
|
||||
public HexInputStream(final byte[] data, final int mbrSize) throws HexFileValidationException, IOException {
|
||||
super(new ByteArrayInputStream(data));
|
||||
this.localBuf = new byte[LINE_LENGTH];
|
||||
this.localPos = LINE_LENGTH; // we are at the end of the local buffer, new one must be obtained
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.exception;
|
||||
package no.nordicsemi.android.dfu.internal.exception;
|
||||
|
||||
/**
|
||||
* Device has disconnected.
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.exception;
|
||||
package no.nordicsemi.android.dfu.internal.exception;
|
||||
|
||||
import no.nordicsemi.android.dfu.DfuBaseService;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.exception;
|
||||
package no.nordicsemi.android.dfu.internal.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.exception;
|
||||
package no.nordicsemi.android.dfu.internal.exception;
|
||||
|
||||
/**
|
||||
* A DFU error occurred on the remote DFU target.
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.exception;
|
||||
package no.nordicsemi.android.dfu.internal.exception;
|
||||
|
||||
public class UnknownResponseException extends Exception {
|
||||
private static final long serialVersionUID = -8716125467309979289L;
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.exception;
|
||||
package no.nordicsemi.android.dfu.internal.exception;
|
||||
|
||||
public class UploadAbortedException extends Exception {
|
||||
private static final long serialVersionUID = -6901728550661937942L;
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package no.nordicsemi.android.dfu.manifest;
|
||||
package no.nordicsemi.android.dfu.internal.manifest;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package no.nordicsemi.android.dfu.manifest;
|
||||
package no.nordicsemi.android.dfu.internal.manifest;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package no.nordicsemi.android.dfu.manifest;
|
||||
package no.nordicsemi.android.dfu.internal.manifest;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package no.nordicsemi.android.dfu.manifest;
|
||||
package no.nordicsemi.android.dfu.internal.manifest;
|
||||
|
||||
public class ManifestFile {
|
||||
protected Manifest manifest;
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package no.nordicsemi.android.dfu.manifest;
|
||||
package no.nordicsemi.android.dfu.internal.manifest;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.scanner;
|
||||
package no.nordicsemi.android.dfu.internal.scanner;
|
||||
|
||||
/**
|
||||
* <p>
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.scanner;
|
||||
package no.nordicsemi.android.dfu.internal.scanner;
|
||||
|
||||
import android.os.Build;
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.scanner;
|
||||
package no.nordicsemi.android.dfu.internal.scanner;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
|
@ -20,7 +20,7 @@
|
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
************************************************************************************************************************************************/
|
||||
|
||||
package no.nordicsemi.android.dfu.scanner;
|
||||
package no.nordicsemi.android.dfu.internal.scanner;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.bluetooth.BluetoothAdapter;
|
Loading…
Reference in New Issue