true if devices must have GENERAL_DISCOVERABLE or LIMITED_DISCOVERABLE flags set in their advertisement packet
* @see #getFilterUUID()
*/
- private void showDeviceScanningDialog(final UUID filter, final boolean discoverableRequired) {
+ private void showDeviceScanningDialog(final UUID filter) {
runOnUiThread(new Runnable() {
@Override
public void run() {
- final ScannerFragment dialog = ScannerFragment.getInstance(BleProfileActivity.this, filter, discoverableRequired);
+ final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
}
});
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java
index edddbeb2..b543b9f9 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java
@@ -185,7 +185,7 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
if (isBLEEnabled()) {
if (!mDeviceConnected) {
setDefaultUI();
- showDeviceScanningDialog(getFilterUUID(), isDiscoverableRequired());
+ showDeviceScanningDialog(getFilterUUID());
} else {
mBleManager.disconnect();
}
@@ -222,8 +222,9 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
}
}
+ mDeviceName = name;
mBleManager.setLogger(mLogSession);
- mDeviceNameView.setText(mDeviceName = name);
+ mDeviceNameView.setText(name != null ? name : getString(R.string.not_available));
mConnectButton.setText(R.string.action_disconnect);
mBleManager.connect(device);
}
@@ -396,28 +397,18 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
*/
protected abstract UUID getFilterUUID();
- /**
- * Whether the scanner must search only for devices with GENERAL_DISCOVERABLE or LIMITER_DISCOVERABLE flag set.
- *
- * @return true if devices must have one of those flags set in their advertisement packets
- */
- protected boolean isDiscoverableRequired() {
- return true;
- }
-
/**
* Shows the scanner fragment.
*
* @param filter the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
- * @param discoverableRequired true if devices must have GENERAL_DISCOVERABLE or LIMITED_DISCOVERABLE flags set in their advertisement packet
* @see #getFilterUUID()
*/
- private void showDeviceScanningDialog(final UUID filter, final boolean discoverableRequired) {
+ private void showDeviceScanningDialog(final UUID filter) {
runOnUiThread(new Runnable() {
@Override
public void run() {
- final ScannerFragment dialog = ScannerFragment.getInstance(BleProfileExpandableListActivity.this, filter, discoverableRequired);
+ final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
}
});
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java
index 3f0c1612..dd182783 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java
@@ -218,7 +218,8 @@ public abstract class BleProfileServiceReadyActivitytrue if devices must have GENERAL_DISCOVERABLE or LIMITED_DISCOVERABLE flags set in their advertisement packet
* @see #getFilterUUID()
*/
- private void showDeviceScanningDialog(final UUID filter, final boolean discoverableRequired) {
- final ScannerFragment dialog = ScannerFragment.getInstance(BleProfileServiceReadyActivity.this, filter, discoverableRequired);
+ private void showDeviceScanningDialog(final UUID filter) {
+ final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
}
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java
index 84f53aba..a7a7e921 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java
@@ -32,6 +32,7 @@ import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
+import android.support.v7.app.NotificationCompat;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
@@ -227,13 +228,14 @@ public class ProximityService extends BleProfileService implements ProximityMana
// both activities above have launchMode="singleTask" in the AndroidManifest.xml file, so if the task is already running, it will be resumed
final PendingIntent pendingIntent = PendingIntent.getActivities(this, OPEN_ACTIVITY_REQ, new Intent[] { parentIntent, targetIntent }, PendingIntent.FLAG_UPDATE_CURRENT);
- final Notification.Builder builder = new Notification.Builder(this).setContentIntent(pendingIntent);
+ final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+ builder.setContentIntent(pendingIntent);
builder.setContentTitle(getString(R.string.app_name)).setContentText(getString(messageResId, getDeviceName()));
builder.setSmallIcon(R.drawable.ic_stat_notify_proximity);
builder.setShowWhen(defaults != 0).setDefaults(defaults).setAutoCancel(true).setOngoing(true);
- builder.addAction(R.drawable.ic_action_bluetooth, getString(R.string.proximity_notification_action_disconnect), disconnectAction);
+ builder.addAction(new NotificationCompat.Action(R.drawable.ic_action_bluetooth, getString(R.string.proximity_notification_action_disconnect), disconnectAction));
if (isConnected())
- builder.addAction(R.drawable.ic_stat_notify_proximity, getString(isImmediateAlertOn ? R.string.proximity_action_silentme : R.string.proximity_action_findme), secondAction);
+ builder.addAction(new NotificationCompat.Action(R.drawable.ic_stat_notify_proximity, getString(isImmediateAlertOn ? R.string.proximity_action_silentme : R.string.proximity_action_findme), secondAction));
final Notification notification = builder.build();
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java
index 47fc12ef..9e36a3ad 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/rsc/RSCService.java
@@ -31,6 +31,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
+import android.support.v7.app.NotificationCompat;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
@@ -186,11 +187,12 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
// both activities above have launchMode="singleTask" in the AndroidManifest.xml file, so if the task is already running, it will be resumed
final PendingIntent pendingIntent = PendingIntent.getActivities(this, OPEN_ACTIVITY_REQ, new Intent[] { parentIntent, targetIntent }, PendingIntent.FLAG_UPDATE_CURRENT);
- final Notification.Builder builder = new Notification.Builder(this).setContentIntent(pendingIntent);
+ final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+ builder.setContentIntent(pendingIntent);
builder.setContentTitle(getString(R.string.app_name)).setContentText(getString(messageResId, getDeviceName()));
builder.setSmallIcon(R.drawable.ic_stat_notify_rsc);
builder.setShowWhen(defaults != 0).setDefaults(defaults).setAutoCancel(true).setOngoing(true);
- builder.addAction(R.drawable.ic_action_bluetooth, getString(R.string.rsc_notification_action_disconnect), disconnectAction);
+ builder.addAction(new NotificationCompat.Action(R.drawable.ic_action_bluetooth, getString(R.string.rsc_notification_action_disconnect), disconnectAction));
final Notification notification = builder.build();
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/scanner/DeviceListAdapter.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/scanner/DeviceListAdapter.java
index c9079a34..a38289c4 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/scanner/DeviceListAdapter.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/scanner/DeviceListAdapter.java
@@ -21,6 +21,7 @@
*/
package no.nordicsemi.android.nrftoolbox.scanner;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@@ -30,8 +31,11 @@ import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
import no.nordicsemi.android.nrftoolbox.R;
+import no.nordicsemi.android.support.v18.scanner.ScanResult;
/**
* DeviceListAdapter class is list adapter for showing scanned Devices name, address and RSSI image based on RSSI values.
@@ -44,56 +48,48 @@ public class DeviceListAdapter extends BaseAdapter {
private final ArrayListnull.
- * - * For further details on parsing BLE advertisement packet data see https://developer.bluetooth.org/Pages/default.aspx Bluetooth Core Specifications Volume 3, Part C, and Section 8 - *
- */ - public static boolean decodeDeviceAdvData(byte[] data, UUID requiredUUID, boolean discoverableRequired) { - final String uuid = requiredUUID != null ? requiredUUID.toString() : null; - if (data != null) { - boolean connectible = !discoverableRequired; - boolean valid = uuid == null; - if (connectible && valid) - return true; - int fieldLength, fieldName; - int packetLength = data.length; - for (int index = 0; index < packetLength; index++) { - fieldLength = data[index]; - if (fieldLength == 0) { - return connectible && valid; - } - fieldName = data[++index]; - - if (uuid != null) { - if (fieldName == SERVICES_MORE_AVAILABLE_16_BIT || fieldName == SERVICES_COMPLETE_LIST_16_BIT) { - for (int i = index + 1; i < index + fieldLength - 1; i += 2) - valid = valid || decodeService16BitUUID(uuid, data, i, 2); - } else if (fieldName == SERVICES_MORE_AVAILABLE_32_BIT || fieldName == SERVICES_COMPLETE_LIST_32_BIT) { - for (int i = index + 1; i < index + fieldLength - 1; i += 4) - valid = valid || decodeService32BitUUID(uuid, data, i, 4); - } else if (fieldName == SERVICES_MORE_AVAILABLE_128_BIT || fieldName == SERVICES_COMPLETE_LIST_128_BIT) { - for (int i = index + 1; i < index + fieldLength - 1; i += 16) - valid = valid || decodeService128BitUUID(uuid, data, i, 16); - } - } - if (!connectible && fieldName == FLAGS_BIT) { - int flags = data[index + 1]; - connectible = (flags & (LE_GENERAL_DISCOVERABLE_MODE | LE_LIMITED_DISCOVERABLE_MODE)) > 0; - } - index += fieldLength - 1; - } - return connectible && valid; - } - return false; - } - - /** - * Decodes the device name from Complete Local Name or Shortened Local Name field in Advertisement packet. Usually if should be done by {@link BluetoothDevice#getName()} method but some phones - * skips that, f.e. Sony Xperia Z1 (C6903) with Android 4.3 where getName() always returnsnull. In order to show the device name correctly we have to parse it manually :(
- */
- public static String decodeDeviceName(byte[] data) {
- String name = null;
- int fieldLength, fieldName;
- int packetLength = data.length;
- for (int index = 0; index < packetLength; index++) {
- fieldLength = data[index];
- if (fieldLength == 0)
- break;
- fieldName = data[++index];
-
- if (fieldName == COMPLETE_LOCAL_NAME || fieldName == SHORTENED_LOCAL_NAME) {
- name = decodeLocalName(data, index + 1, fieldLength - 1);
- break;
- }
- index += fieldLength - 1;
- }
- return name;
- }
-
- /**
- * Decodes the local name
- */
- public static String decodeLocalName(final byte[] data, final int start, final int length) {
- try {
- return new String(data, start, length, "UTF-8");
- } catch (final UnsupportedEncodingException e) {
- Log.e(TAG, "Unable to convert the complete local name to UTF-8", e);
- return null;
- } catch (final IndexOutOfBoundsException e) {
- Log.e(TAG, "Error when reading complete local name", e);
- return null;
- }
- }
-
- /**
- * check for required Service UUID inside device
- */
- private static boolean decodeService16BitUUID(String uuid, byte[] data, int startPosition, int serviceDataLength) {
- String serviceUUID = Integer.toHexString(decodeUuid16(data, startPosition));
- String requiredUUID = uuid.substring(4, 8);
-
- return serviceUUID.equals(requiredUUID);
- }
-
- /**
- * check for required Service UUID inside device
- */
- private static boolean decodeService32BitUUID(String uuid, byte[] data, int startPosition, int serviceDataLength) {
- String serviceUUID = Integer.toHexString(decodeUuid16(data, startPosition + serviceDataLength - 4));
- String requiredUUID = uuid.substring(4, 8);
-
- return serviceUUID.equals(requiredUUID);
- }
-
- /**
- * check for required Service UUID inside device
- */
- private static boolean decodeService128BitUUID(String uuid, byte[] data, int startPosition, int serviceDataLength) {
- String serviceUUID = Integer.toHexString(decodeUuid16(data, startPosition + serviceDataLength - 4));
- String requiredUUID = uuid.substring(4, 8);
-
- return serviceUUID.equals(requiredUUID);
- }
-
- private static int decodeUuid16(final byte[] data, final int start) {
- final int b1 = data[start] & 0xff;
- final int b2 = data[start + 1] & 0xff;
-
- return (b2 << 8 | b1);
- }
-}
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/template/TemplateService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/template/TemplateService.java
index 6b0ba5d4..8150586b 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/template/TemplateService.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/template/TemplateService.java
@@ -30,6 +30,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
+import android.support.v7.app.NotificationCompat;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
@@ -141,11 +142,12 @@ public class TemplateService extends BleProfileService implements TemplateManage
// both activities above have launchMode="singleTask" in the AndroidManifest.xml file, so if the task is already running, it will be resumed
final PendingIntent pendingIntent = PendingIntent.getActivities(this, OPEN_ACTIVITY_REQ, new Intent[] { parentIntent, targetIntent }, PendingIntent.FLAG_UPDATE_CURRENT);
- final Notification.Builder builder = new Notification.Builder(this).setContentIntent(pendingIntent);
+ final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+ builder.setContentIntent(pendingIntent);
builder.setContentTitle(getString(R.string.app_name)).setContentText(getString(messageResId, getDeviceName()));
builder.setSmallIcon(R.drawable.ic_stat_notify_template);
builder.setShowWhen(defaults != 0).setDefaults(defaults).setAutoCancel(true).setOngoing(true);
- builder.addAction(R.drawable.ic_action_bluetooth, getString(R.string.template_notification_action_disconnect), disconnectAction);
+ builder.addAction(new NotificationCompat.Action(R.drawable.ic_action_bluetooth, getString(R.string.template_notification_action_disconnect), disconnectAction));
final Notification notification = builder.build();
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/UARTActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/UARTActivity.java
index 800b909b..db731f4e 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/UARTActivity.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/UARTActivity.java
@@ -22,38 +22,131 @@
package no.nordicsemi.android.nrftoolbox.uart;
+import android.Manifest;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.TransitionDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.DialogFragment;
import android.support.v4.widget.SlidingPaneLayout;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.NotificationCompat;
+import android.util.Log;
+import android.view.Menu;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.Toast;
+import org.simpleframework.xml.Serializer;
+import org.simpleframework.xml.core.Persister;
+import org.simpleframework.xml.strategy.Strategy;
+import org.simpleframework.xml.strategy.Type;
+import org.simpleframework.xml.strategy.Visitor;
+import org.simpleframework.xml.strategy.VisitorStrategy;
+import org.simpleframework.xml.stream.Format;
+import org.simpleframework.xml.stream.HyphenStyle;
+import org.simpleframework.xml.stream.InputNode;
+import org.simpleframework.xml.stream.NodeMap;
+import org.simpleframework.xml.stream.OutputNode;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
import java.util.UUID;
import no.nordicsemi.android.nrftoolbox.R;
+import no.nordicsemi.android.nrftoolbox.dfu.adapter.FileBrowserAppsAdapter;
import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
import no.nordicsemi.android.nrftoolbox.profile.BleProfileServiceReadyActivity;
+import no.nordicsemi.android.nrftoolbox.uart.database.DatabaseHelper;
+import no.nordicsemi.android.nrftoolbox.uart.domain.Command;
+import no.nordicsemi.android.nrftoolbox.uart.domain.UartConfiguration;
+import no.nordicsemi.android.nrftoolbox.utility.FileHelper;
+import no.nordicsemi.android.nrftoolbox.widget.ClosableSpinner;
-public class UARTActivity extends BleProfileServiceReadyActivity+ * ---------------------------------------------------------------------------- + * CONFIGURATIONS | + * ---------------------------------------------------------------------------- + * | _id (int, pk, auto increment) | name (text) | xml (text) | deleted (int) | + * ---------------------------------------------------------------------------- + *+ */ + private static final String CREATE_CONFIGURATIONS = "CREATE TABLE " + Tables.CONFIGURATIONS+ "(" + ConfigurationContract.Configuration._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + ConfigurationContract.Configuration.NAME + " TEXT UNIQUE NOT NULL, " + ConfigurationContract.Configuration.XML + " TEXT NOT NULL, " + ConfigurationContract.Configuration.DELETED +" INTEGER NOT NULL DEFAULT(0))"; + + private static final String DROP_IF_EXISTS = "DROP TABLE IF EXISTS "; + + public SQLiteHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(final SQLiteDatabase db) { + db.execSQL(CREATE_CONFIGURATIONS); + } + + @Override + public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + // This method does nothing for now. + switch (oldVersion) { + case 1: + // do nothing + } + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/database/NameColumns.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/database/NameColumns.java new file mode 100644 index 00000000..a74678ec --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/database/NameColumns.java @@ -0,0 +1,28 @@ +/* + * 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.nrftoolbox.uart.database; + +public interface NameColumns { + /** The name */ + public final static String NAME = "name"; +} \ No newline at end of file diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/database/UndoColumns.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/database/UndoColumns.java new file mode 100644 index 00000000..eafacb32 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/database/UndoColumns.java @@ -0,0 +1,27 @@ +/************************************************************************************************************************************************* + * 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.nrftoolbox.uart.database; + +public interface UndoColumns { + /** The 'deleted' flag */ + public final static String DELETED = "deleted"; +} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/domain/Command.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/domain/Command.java new file mode 100644 index 00000000..6b4c13e1 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/domain/Command.java @@ -0,0 +1,116 @@ +/* + * 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.nrftoolbox.uart.domain; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.Root; +import org.simpleframework.xml.Text; + +@Root +public class Command { + public enum Icon { + LEFT(0), + UP(1), + RIGHT(2), + DOWN(3), + SETTINGS(4), + REW(5), + PLAY(6), + PAUSE(7), + STOP(8), + FWD(9), + INFO(10), + NUMBER_1(11), + NUMBER_2(12), + NUMBER_3(13), + NUMBER_4(14), + NUMBER_5(15), + NUMBER_6(16), + NUMBER_7(17), + NUMBER_8(18), + NUMBER_9(19); + + public int index; + + private Icon(final int index) { + this.index = index; + } + } + + @Text(required = false) + private String command; + + @Attribute(required = false) + private boolean active = false; + + @Attribute(required = false) + private Icon icon = Icon.LEFT; + + /** + * Sets the command. + * @param command the command that will be sent to UART device + */ + public void setCommand(final String command) { + this.command = command; + } + + /** + * Sets whether the command is active. + * @param active true to make it active + */ + public void setActive(boolean active) { + this.active = active; + } + + /** + * Sets the icon index. + * @param index index of the icon. + */ + public void setIconIndex(final int index) { + this.icon = Icon.values()[index]; + } + + /** + * Returns the command that will be sent to UART device. + * @return the command + */ + public String getCommand() { + return command; + } + + /** + * Returns whether the icon is active. + * @return true if it's active + */ + public boolean isActive() { + return active; + } + + /** + * Returns the icon index. + * @return the icon index + */ + public int getIconIndex() { + return icon.index; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/domain/UartConfiguration.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/domain/UartConfiguration.java new file mode 100644 index 00000000..981f48ce --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/uart/domain/UartConfiguration.java @@ -0,0 +1,71 @@ +/* + * 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.nrftoolbox.uart.domain; + +import org.simpleframework.xml.Attribute; +import org.simpleframework.xml.ElementArray; +import org.simpleframework.xml.Root; +import org.simpleframework.xml.core.PersistenceException; +import org.simpleframework.xml.core.Validate; + +@Root +public class UartConfiguration { + public static final int COMMANDS_COUNT = 9; + + @Attribute(required = false, empty = "Unnamed") + private String name; + + @ElementArray + private Command[] commands = new Command[COMMANDS_COUNT]; + + /** + * Returns the field name + * + * @return optional name + */ + public String getName() { + return name; + } + + /** + * Sets the name to specified value + * @param name the new name + */ + public void setName(final String name) { + this.name = name; + } + + /** + * Returns the array of commands. There is always 9 of them. + * @return the commands array + */ + public Command[] getCommands() { + return commands; + } + + @Validate + private void validate() throws PersistenceException{ + if (commands == null || commands.length != COMMANDS_COUNT) + throw new PersistenceException("There must be always " + COMMANDS_COUNT + " commands in a configuration."); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/utility/FileHelper.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/utility/FileHelper.java new file mode 100644 index 00000000..ed1f9c20 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/utility/FileHelper.java @@ -0,0 +1,215 @@ +/* + * 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.nrftoolbox.utility; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Environment; +import android.preference.PreferenceManager; +import android.widget.Toast; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import no.nordicsemi.android.nrftoolbox.R; + +public class FileHelper { + private static final String TAG = "FileHelper"; + + private static final String PREFS_SAMPLES_VERSION = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_SAMPLES_VERSION"; + private static final int CURRENT_SAMPLES_VERSION = 4; + + public static final String NORDIC_FOLDER = "Nordic Semiconductor"; + public static final String UART_FOLDER = "UART Configurations"; + public static final String BOARD_FOLDER = "Board"; + public static final String BOARD_NRF6310_FOLDER = "nrf6310"; + public static final String BOARD_PCA10028_FOLDER = "pca10028"; + public static final String BOARD_PCA10036_FOLDER = "pca10036"; + + public static boolean newSamplesAvailable(final Context context) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + final int version = preferences.getInt(PREFS_SAMPLES_VERSION, 0); + return version < CURRENT_SAMPLES_VERSION; + } + + public static void createSamples(final Context context) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + final int version = preferences.getInt(PREFS_SAMPLES_VERSION, 0); + if (version == CURRENT_SAMPLES_VERSION) + return; + + /* + * Copy example HEX files to the external storage. Files will be copied if the DFU Applications folder is missing + */ + final File root = new File(Environment.getExternalStorageDirectory(), "Nordic Semiconductor"); + if (!root.exists()) { + root.mkdir(); + } + final File board = new File(root, "Board"); + if (!board.exists()) { + board.mkdir(); + } + final File nrf6310 = new File(board, "nrf6310"); + if (!nrf6310.exists()) { + nrf6310.mkdir(); + } + final File pca10028 = new File(board, "pca10028"); + if (!pca10028.exists()) { + pca10028.mkdir(); + } + + // Remove old files. Those will be moved to a new folder structure + new File(root, "ble_app_hrs_s110_v6_0_0.hex").delete(); + new File(root, "ble_app_rscs_s110_v6_0_0.hex").delete(); + new File(root, "ble_app_hrs_s110_v7_0_0.hex").delete(); + new File(root, "ble_app_rscs_s110_v7_0_0.hex").delete(); + new File(root, "blinky_arm_s110_v7_0_0.hex").delete(); + new File(root, "dfu_2_0.bat").delete(); // This file has been migrated to 3.0 + new File(root, "dfu_3_0.bat").delete(); // This file has been migrated to 3.1 + new File(root, "dfu_2_0.sh").delete(); // This file has been migrated to 3.0 + new File(root, "dfu_3_0.sh").delete(); // This file has been migrated to 3.1 + new File(root, "README.txt").delete(); // This file has been modified to match v.3.0+ + + boolean oldCopied = false; + boolean newCopied = false; + + // nrf6310 files + File f = new File(nrf6310, "ble_app_hrs_s110_v6_0_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_s110_v6_0_0, f); + oldCopied = true; + } + f = new File(nrf6310, "ble_app_rscs_s110_v6_0_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_rscs_s110_v6_0_0, f); + oldCopied = true; + } + f = new File(nrf6310, "ble_app_hrs_s110_v7_0_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_s110_v7_0_0, f); + oldCopied = true; + } + f = new File(nrf6310, "ble_app_rscs_s110_v7_0_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_rscs_s110_v7_0_0, f); + oldCopied = true; + } + f = new File(nrf6310, "blinky_arm_s110_v7_0_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.blinky_arm_s110_v7_0_0, f); + oldCopied = true; + } + // PCA10028 files + f = new File(pca10028, "blinky_s110_v7_1_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.blinky_s110_v7_1_0, f); + oldCopied = true; + } + f = new File(pca10028, "blinky_s110_v7_1_0_ext_init.dat"); + if (!f.exists()) { + copyRawResource(context, R.raw.blinky_s110_v7_1_0_ext_init, f); + oldCopied = true; + } + f = new File(pca10028, "ble_app_hrs_dfu_s110_v7_1_0.hex"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_dfu_s110_v7_1_0, f); + oldCopied = true; + } + f = new File(pca10028, "ble_app_hrs_dfu_s110_v7_1_0_ext_init.dat"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_dfu_s110_v7_1_0_ext_init, f); + oldCopied = true; + } + new File(root, "ble_app_hrs_dfu_s110_v8_0_0.zip").delete(); // name changed + f = new File(pca10028, "ble_app_hrs_dfu_s110_v8_0_0_sdk_v8_0.zip"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_dfu_s110_v8_0_0_sdk_v8_0, f); + newCopied = true; + } + f = new File(pca10028, "ble_app_hrs_dfu_s110_v8_0_0_sdk_v9_0.zip"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_dfu_s110_v8_0_0_sdk_v9_0, f); + newCopied = true; + } + f = new File(pca10028, "ble_app_hrs_dfu_all_in_one_sdk_v9_0.zip"); + if (!f.exists()) { + copyRawResource(context, R.raw.ble_app_hrs_dfu_all_in_one_sdk_v9_0, f); + newCopied = true; + } + + if (oldCopied) + Toast.makeText(context, R.string.dfu_example_files_created, Toast.LENGTH_SHORT).show(); + else if (newCopied) + Toast.makeText(context, R.string.dfu_example_new_files_created, Toast.LENGTH_SHORT).show(); + + // Scripts + newCopied = false; + f = new File(root, "dfu_3_1.bat"); + if (!f.exists()) { + copyRawResource(context, R.raw.dfu_win_3_1, f); + newCopied = true; + } + f = new File(root, "dfu_3_1.sh"); + if (!f.exists()) { + copyRawResource(context, R.raw.dfu_mac_3_1, f); + newCopied = true; + } + f = new File(root, "README.txt"); + if (!f.exists()) { + copyRawResource(context, R.raw.readme, f); + } + if (newCopied) + Toast.makeText(context, R.string.dfu_scripts_created, Toast.LENGTH_SHORT).show(); + + // Save the current version + preferences.edit().putInt(PREFS_SAMPLES_VERSION, CURRENT_SAMPLES_VERSION).apply(); + } + + /** + * Copies the file from res/raw with given id to given destination file. If dest does not exist it will be created. + * + * @param context activity context + * @param rawResId the resource id + * @param dest destination file + */ + private static void copyRawResource(final Context context, final int rawResId, final File dest) { + try { + final InputStream is = context.getResources().openRawResource(rawResId); + final FileOutputStream fos = new FileOutputStream(dest); + + final byte[] buf = new byte[1024]; + int read; + try { + while ((read = is.read(buf)) > 0) + fos.write(buf, 0, read); + } finally { + is.close(); + fos.close(); + } + } catch (final IOException e) { + DebugLogger.e(TAG, "Error while copying HEX file " + e.toString()); + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/widget/ClosableSpinner.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/widget/ClosableSpinner.java new file mode 100644 index 00000000..30a94d89 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/widget/ClosableSpinner.java @@ -0,0 +1,37 @@ +/* + * 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.nrftoolbox.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Spinner; + +public class ClosableSpinner extends Spinner { + public ClosableSpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void close() { + super.onDetachedFromWindow(); + } +} diff --git a/app/src/main/res/drawable-hdpi/item_background_light_n.9.png b/app/src/main/res/drawable-hdpi/item_background_light_n.9.png deleted file mode 100644 index 0c8a9451..00000000 Binary files a/app/src/main/res/drawable-hdpi/item_background_light_n.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/item_background_light_p.9.png b/app/src/main/res/drawable-hdpi/item_background_light_p.9.png deleted file mode 100644 index 74947f36..00000000 Binary files a/app/src/main/res/drawable-hdpi/item_background_light_p.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-v21/ic_icon_button_background.xml b/app/src/main/res/drawable-v21/ic_icon_button_background.xml new file mode 100644 index 00000000..6b1e883b --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_icon_button_background.xml @@ -0,0 +1,18 @@ + + + +