blob: 44fbd5044fc3356da963fbb16c1bc835985339be [file] [log] [blame]
/**
* **********************************************************************************************************************************************
* 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 DfuServiceInitiator class may be used to make this process easier. It provides simple API that covers all low lever operations.
*/
public class DfuServiceInitiator {
private final String deviceAddress;
private String deviceName;
private boolean disableNotification;
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 DfuServiceInitiator(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 DfuServiceInitiator setDeviceName(final String name) {
this.deviceName = name;
return this;
}
/**
* Sets whether the progress notification in the status bar should be disabled.
* Defaults to false.
* @param disableNotification whether to disable the notification
* @return the builder
*/
public DfuServiceInitiator setDisableNotification(final boolean disableNotification) {
this.disableNotification = disableNotification;
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 DfuServiceInitiator 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 uri the URI of the file
* @return the builder
* @see #setZip(String)
* @see #setZip(int)
*/
public DfuServiceInitiator setZip(final Uri uri) {
return init(uri, null, 0, DfuBaseService.TYPE_AUTO, DfuBaseService.MIME_TYPE_ZIP);
}
/**
* Sets the path to the Distribution packet (ZIP) or the a ZIP file matching the deprecated naming convention.
* @param path path to the file
* @return the builder
* @see #setZip(Uri)
* @see #setZip(int)
*/
public DfuServiceInitiator setZip(final String path) {
return init(null, path, 0, DfuBaseService.TYPE_AUTO, 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 rawResId file's resource ID
* @return the builder
* @see #setZip(Uri)
* @see #setZip(String)
*/
public DfuServiceInitiator setZip(final int rawResId) {
return init(null, null, rawResId, DfuBaseService.TYPE_AUTO, 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 uri the URI of the file
* @param path the path of the file
* @return the builder
*/
public DfuServiceInitiator setZip(final Uri uri, final String path) {
return init(uri, path, 0, DfuBaseService.TYPE_AUTO, 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 DfuServiceInitiator 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 DfuServiceInitiator 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 The Distribution packet (ZIP) should be used for DFU Bootloader version 0.5 or newer
*/
@Deprecated
public DfuServiceInitiator 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(uri, 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 DfuServiceInitiator 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 DfuServiceInitiator 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 DfuServiceInitiator 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 DfuServiceInitiator 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 DfuServiceInitiator 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_DISABLE_NOTIFICATION, disableNotification);
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 DfuServiceInitiator 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 DfuServiceInitiator 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;
}
}