DFU Starter and ListenerHelper.

This commit is contained in:
Aleksander Nowakowski 2015-07-21 16:50:55 +02:00
parent c0e753a420
commit 4044524cb6
23 changed files with 954 additions and 48 deletions

View File

@ -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.

View File

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

View File

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

View File

@ -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
}
}

View File

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

View File

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

View File

@ -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+,

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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;