diff --git a/app/build.gradle b/app/build.gradle
index d359e0d..858b712 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,15 +1,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 27
- buildToolsVersion "27.0.3"
-
+ compileSdkVersion 29
defaultConfig {
applicationId "com.dataart.btle_android"
- minSdkVersion 19
- targetSdkVersion 27
- versionCode 3
- versionName "3.0"
+ minSdkVersion 21
+ targetSdkVersion 29
+ versionCode 4
+ versionName "4.0"
multiDexEnabled true
}
buildTypes {
@@ -27,23 +25,24 @@ android {
ext {
devicehive = "3.1.2"
commons = "1.11"
- rxandroid = "2.0.1"
- rxjava = "2.1.7"
- guava = "23.6-android"
- gson = "2.8.2"
- timber = "4.6.0"
+ rxandroid = "2.1.1"
+ rxjava = "2.2.19"
+ guava = "24.1-jre"
+ gson = "2.8.6"
+ timber = "4.7.1"
support = "27.0.2"
- gms = "11.8.0"
- multidex = "1.0.2"
+ gms = "17.0.0"
+ materialVersion = '1.3.0-alpha02'
+ constraintLayoutVersion = '2.0.1'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation "com.android.support:appcompat-v7:${support}"
- implementation "com.android.support:design:${support}"
-
+ implementation "com.google.android.material:material:$materialVersion"
implementation "com.google.code.gson:gson:${gson}"
+ implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion"
+
implementation "com.jakewharton.timber:timber:${timber}"
implementation "commons-codec:commons-codec:${commons}"
@@ -58,5 +57,4 @@ dependencies {
implementation "com.google.guava:guava:${guava}"
implementation "com.github.devicehive:devicehive-java:${devicehive}"
- implementation "com.android.support:multidex:${multidex}"
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 65318a6..f47f990 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,7 @@
+
diff --git a/app/src/main/java/com/dataart/btle_android/BTLEApplication.java b/app/src/main/java/com/dataart/btle_android/BTLEApplication.java
index 0e63f57..68be216 100644
--- a/app/src/main/java/com/dataart/btle_android/BTLEApplication.java
+++ b/app/src/main/java/com/dataart/btle_android/BTLEApplication.java
@@ -1,17 +1,14 @@
package com.dataart.btle_android;
-import android.support.multidex.MultiDex;
-import android.support.multidex.MultiDexApplication;
-
+import android.app.Application;
import com.dataart.btle_android.devicehive.BTLEDevicePreferences;
-
import timber.log.Timber;
/**
* Created by alrybakov
*/
-public class BTLEApplication extends MultiDexApplication {
+public class BTLEApplication extends Application {
private static BTLEApplication application;
@@ -23,7 +20,6 @@ public static BTLEApplication getApplication() {
public void onCreate() {
super.onCreate();
application = this;
- MultiDex.install(this);
BTLEDevicePreferences.getInstance().init(this);
if (BuildConfig.DEBUG){
Timber.plant(new Timber.DebugTree());
diff --git a/app/src/main/java/com/dataart/btle_android/MainActivity.java b/app/src/main/java/com/dataart/btle_android/MainActivity.java
index 6511d29..d945ec7 100644
--- a/app/src/main/java/com/dataart/btle_android/MainActivity.java
+++ b/app/src/main/java/com/dataart/btle_android/MainActivity.java
@@ -8,22 +8,24 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.inputmethod.EditorInfo;
-import android.widget.Button;
-import android.widget.EditText;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+
import com.dataart.btle_android.btle_gateway.BluetoothLeService;
import com.dataart.btle_android.devicehive.BTLEDevicePreferences;
import com.dataart.btle_android.helpers.BleHelpersFactory;
import com.dataart.btle_android.helpers.ble.base.BleInitializer;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
import java.util.Objects;
import java.util.UUID;
@@ -36,12 +38,15 @@ public class MainActivity extends AppCompatActivity {
private BleInitializer bleInitializer;
private BluetoothManager mBluetoothManager;
- private EditText serverUrlEditText;
- private EditText gatewayIdEditText;
- private EditText refreshTokenEditText;
+ private TextInputEditText serverUrlEditText;
+ private TextInputLayout serverUrlEditTextParent;
+ private TextInputEditText gatewayIdEditText;
+ private TextInputLayout gatewayIdEditTextParent;
+ private TextInputEditText refreshTokenEditText;
+ private TextInputLayout refreshTokenEditTextParent;
private TextView hintText;
- private Button serviceButton;
- private Button restartServiceButton;
+ private FloatingActionButton serviceButton;
+ private FloatingActionButton restartServiceButton;
private BTLEDevicePreferences prefs;
private boolean isServiceStarted;
private final View.OnClickListener restartClickListener = new View.OnClickListener() {
@@ -83,11 +88,6 @@ public void afterTextChanged(Editable editable) {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
- Toolbar myToolbar = findViewById(R.id.toolbar);
- setSupportActionBar(myToolbar);
- if (getSupportActionBar() != null) {
- getSupportActionBar().setTitle(R.string.app_name);
- }
// BleInitializer will start service on initialization success
bleInitializer = BleHelpersFactory.getInitializer(this, bluetoothAdapter -> startService());
init();
@@ -114,8 +114,11 @@ private void init() {
prefs = BTLEDevicePreferences.getInstance();
serverUrlEditText = findViewById(R.id.server_url_edit);
+ serverUrlEditTextParent = findViewById(R.id.server_url_parent);
gatewayIdEditText = findViewById(R.id.settings_gateway_id);
+ gatewayIdEditTextParent = findViewById(R.id.settings_gateway_id_parent);
refreshTokenEditText = findViewById(R.id.refresh_token_edit);
+ refreshTokenEditTextParent = findViewById(R.id.refresh_token_parent);
hintText = findViewById(R.id.hintText);
resetValues();
@@ -212,12 +215,12 @@ private void startService() {
private void onServiceRunning() {
isServiceStarted = true;
- serviceButton.setText(R.string.button_stop);
+ serviceButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_stop));
}
private void onServiceStopped() {
isServiceStarted = false;
- serviceButton.setText(R.string.button_start);
+ serviceButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_play_arrow));
}
private boolean isRestartRequired() {
@@ -234,7 +237,7 @@ private void onDataChanged() {
if (isServiceStarted && isRestartRequired()) {
hintText.setVisibility(View.VISIBLE);
restartServiceButton.setVisibility(View.VISIBLE);
- serviceButton.setVisibility(View.GONE);
+ serviceButton.setVisibility(View.INVISIBLE);
} else {
hintText.setVisibility(View.GONE);
restartServiceButton.setVisibility(View.GONE);
@@ -254,7 +257,7 @@ private void resetValues() {
gatewayIdEditText.setText(
TextUtils.isEmpty(gatewayId)
? getString(R.string.default_gateway_id) + "-" +
- UUID.randomUUID().toString().substring(0, 4)
+ UUID.randomUUID().toString().substring(0, 4)
: gatewayId
);
@@ -267,9 +270,9 @@ private void resetValues() {
}
private void resetErrors() {
- serverUrlEditText.setError(null);
- gatewayIdEditText.setError(null);
- refreshTokenEditText.setError(null);
+ serverUrlEditTextParent.setError(null);
+ gatewayIdEditTextParent.setError(null);
+ refreshTokenEditTextParent.setError(null);
}
private boolean validateValues() {
@@ -280,13 +283,13 @@ private boolean validateValues() {
final String refreshToken = refreshTokenEditText.getText().toString();
if (TextUtils.isEmpty(serverUrl)) {
- serverUrlEditText.setError(getString(R.string.error_message_empty_server_url));
+ serverUrlEditTextParent.setError(getString(R.string.error_message_empty_server_url));
serverUrlEditText.requestFocus();
} else if (TextUtils.isEmpty(gatewayId)) {
- gatewayIdEditText.setError(getString(R.string.error_message_empty_gateway_id));
+ gatewayIdEditTextParent.setError(getString(R.string.error_message_empty_gateway_id));
gatewayIdEditText.requestFocus();
} else if (TextUtils.isEmpty(refreshToken)) {
- refreshTokenEditText.setError(getString(R.string.error_message_empty_refresh_token));
+ refreshTokenEditTextParent.setError(getString(R.string.error_message_empty_refresh_token));
refreshTokenEditText.requestFocus();
} else {
return true;
diff --git a/app/src/main/java/com/dataart/btle_android/btle_gateway/BluetoothLeService.java b/app/src/main/java/com/dataart/btle_android/btle_gateway/BluetoothLeService.java
index f5ac9ee..9f5470e 100644
--- a/app/src/main/java/com/dataart/btle_android/btle_gateway/BluetoothLeService.java
+++ b/app/src/main/java/com/dataart/btle_android/btle_gateway/BluetoothLeService.java
@@ -1,5 +1,7 @@
package com.dataart.btle_android.btle_gateway;
+import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
@@ -10,16 +12,15 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Build;
import android.os.IBinder;
-import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
-
+import androidx.core.app.NotificationCompat;
import com.dataart.btle_android.MainActivity;
import com.dataart.btle_android.R;
import com.dataart.btle_android.btle_gateway.server.BluetoothServer;
import com.dataart.btle_android.devicehive.BTLEDeviceHive;
import com.github.devicehive.client.service.DeviceCommand;
-
import timber.log.Timber;
/**
@@ -33,6 +34,8 @@ public class BluetoothLeService extends Service {
.concat("ACTION_BT_PERMISSION_REQUEST");
private final static int LE_NOTIFICATION_ID = 1;
+ private final static String LE_NOTIFICATION_NAME = "DeviceHive";
+ private final static String LE_NOTIFICATION_CHANNEL_ID = "devicehive";
private NotificationManager mNotificationManager;
private NotificationCompat.Builder mBuilder;
@@ -49,7 +52,11 @@ public BluetoothLeService() {
}
public static void start(final Context context) {
- context.startService(new Intent(context, BluetoothLeService.class));
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ context.startForegroundService(new Intent(context, BluetoothLeService.class));
+ } else {
+ context.startService(new Intent(context, BluetoothLeService.class));
+ }
}
public static void stop(final Context context) {
@@ -86,7 +93,13 @@ public int onStartCommand(Intent intent, int flags, int startId) {
mDeviceHive.registerDevice();
- setNotification();
+ Notification notification = prepareNotification();
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ startForeground(LE_NOTIFICATION_ID, notification);
+ } else {
+ mNotificationManager.notify(LE_NOTIFICATION_ID, mBuilder.build());
+ }
return START_NOT_STICKY;
}
@@ -156,13 +169,20 @@ private void send(final String action) {
sendBroadcast(intent);
}
- private void setNotification() {
+ private Notification prepareNotification() {
final Intent resultIntent = new Intent(this, MainActivity.class);
final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
final PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
- mBuilder = new NotificationCompat.Builder(this, "channel_id_1")
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(LE_NOTIFICATION_CHANNEL_ID, LE_NOTIFICATION_NAME, NotificationManager.IMPORTANCE_HIGH);
+ channel.enableVibration(false);
+ channel.setShowBadge(true);
+ mNotificationManager.createNotificationChannel(channel);
+ }
+
+ mBuilder = new NotificationCompat.Builder(this, LE_NOTIFICATION_CHANNEL_ID)
.setContentText(getString(R.string.notification_bt_on))
.setContentTitle(getString(R.string.device_hive))
.setSmallIcon(R.drawable.ic_le_service)
@@ -170,7 +190,11 @@ private void setNotification() {
.setOngoing(true)
.setContentIntent(resultPendingIntent);
- mNotificationManager.notify(LE_NOTIFICATION_ID, mBuilder.build());
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ mBuilder.setChannelId(LE_NOTIFICATION_CHANNEL_ID);
+ }
+
+ return mBuilder.build();
}
}
diff --git a/app/src/main/java/com/dataart/btle_android/btle_gateway/server/BluetoothServer.java b/app/src/main/java/com/dataart/btle_android/btle_gateway/server/BluetoothServer.java
index b67e271..5956fd0 100644
--- a/app/src/main/java/com/dataart/btle_android/btle_gateway/server/BluetoothServer.java
+++ b/app/src/main/java/com/dataart/btle_android/btle_gateway/server/BluetoothServer.java
@@ -241,7 +241,12 @@ DeviceConnection connectAndSave(String address, BluetoothDevice device, Interact
private DeviceConnection connectAndSave(String address, BluetoothDevice device, InteractiveGattCallback.DisconnectListener disconnectListener, InteractiveGattCallback.StatusListener statusListener, InteractiveGattCallback.OnConnectedListener connectedListener) {
final InteractiveGattCallback callback = new InteractiveGattCallback(address, statusListener, context, disconnectListener, connectedListener);
- BluetoothGatt gatt = device.connectGatt(context, false, callback);
+ BluetoothGatt gatt = null;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ gatt = device.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);
+ } else {
+ gatt = device.connectGatt(context, false, callback);
+ }
DeviceConnection connection = new DeviceConnection(address, gatt, callback);
activeConnections.put(address, connection);
return connection;
diff --git a/app/src/main/java/com/dataart/btle_android/devicehive/BTLEDeviceHive.java b/app/src/main/java/com/dataart/btle_android/devicehive/BTLEDeviceHive.java
index 5efc9ea..6957412 100644
--- a/app/src/main/java/com/dataart/btle_android/devicehive/BTLEDeviceHive.java
+++ b/app/src/main/java/com/dataart/btle_android/devicehive/BTLEDeviceHive.java
@@ -88,10 +88,11 @@ public void run() {
deviceListener.onDeviceReceived(device);
device.subscribeCommands(new CommandFilter(), new DeviceCommandsCallback() {
public void onSuccess(List commands) {
- for(DeviceCommand command: commands) {
+ for (DeviceCommand command : commands) {
notifyListenersCommandReceived(command);
}
}
+
public void onFail(FailureData failureData) {
}
});
@@ -107,7 +108,7 @@ public void disconnect() {
Thread thread = new Thread() {
public void run() {
deviceListener.onDeviceReceived(null);
- deviceHive.unsubscribeAllCommands();
+ if (deviceHive != null) deviceHive.unsubscribeAllCommands();
deviceHive = null;
}
};
diff --git a/app/src/main/java/com/dataart/btle_android/devicehive/DeviceHiveConfig.java b/app/src/main/java/com/dataart/btle_android/devicehive/DeviceHiveConfig.java
index a826b42..80d04a3 100644
--- a/app/src/main/java/com/dataart/btle_android/devicehive/DeviceHiveConfig.java
+++ b/app/src/main/java/com/dataart/btle_android/devicehive/DeviceHiveConfig.java
@@ -2,6 +2,6 @@
public final class DeviceHiveConfig {
- public static final String API_ENDPOINT = "http://playground.devicehive.com/api/rest";
+ public static final String API_ENDPOINT = "https://playground.devicehive.com/api/rest";
}
diff --git a/app/src/main/java/com/dataart/btle_android/helpers/LocationHelper.java b/app/src/main/java/com/dataart/btle_android/helpers/LocationHelper.java
index 61481bf..e7052f3 100644
--- a/app/src/main/java/com/dataart/btle_android/helpers/LocationHelper.java
+++ b/app/src/main/java/com/dataart/btle_android/helpers/LocationHelper.java
@@ -1,6 +1,5 @@
package com.dataart.btle_android.helpers;
-
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -9,9 +8,8 @@
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.dataart.btle_android.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
@@ -26,7 +24,6 @@
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
-
import timber.log.Timber;
/**
diff --git a/app/src/main/res/drawable/ic_play_arrow.xml b/app/src/main/res/drawable/ic_play_arrow.xml
new file mode 100644
index 0000000..a92dd19
--- /dev/null
+++ b/app/src/main/res/drawable/ic_play_arrow.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_repeat.xml b/app/src/main/res/drawable/ic_repeat.xml
new file mode 100644
index 0000000..ca56235
--- /dev/null
+++ b/app/src/main/res/drawable/ic_repeat.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_stop.xml b/app/src/main/res/drawable/ic_stop.xml
new file mode 100644
index 0000000..a9e8c66
--- /dev/null
+++ b/app/src/main/res/drawable/ic_stop.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 0f52517..c967b3f 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -1,132 +1,155 @@
-
-
-
-
+ android:fillViewport="true"
+ android:scrollbars="none"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
-
-
-
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:padding="@dimen/padding">
+
+
+
+
-
-
-
-
-
-
-
-
+ android:hint="@string/settings_server_url"
+ android:imeOptions="actionNext"
+ android:lines="1"
+ android:inputType="text"
+ android:maxLines="1" />
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+ app:layout_constraintBottom_toTopOf="@id/hintText"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/settings_gateway_id_parent">
-
-
-
-
-
+
+
+
+ android:textColor="@color/hint_color"
+ android:visibility="gone"
+ app:drawableStartCompat="@drawable/ic_information"
+ app:layout_constraintBottom_toTopOf="@id/space"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/refresh_token_parent"
+ tools:visibility="visible" />
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
deleted file mode 100644
index 8f851fd..0000000
--- a/app/src/main/res/values-v21/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index e497ead..038d7f6 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,5 +1,8 @@
- #000
- #444
-
\ No newline at end of file
+ #133048
+ #457186
+ #00BCD4
+ #808080
+ #ff858585
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 067384d..592a1d2 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -3,4 +3,8 @@
https://developer.android.com/design/patterns/navigation-drawer.html -->
10dp
4dp
+ 8dp
+ 80dp
+ 80dp
+ 24dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0fbc2f4..ac0a52b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,7 +11,7 @@
Start service
Stop service
- http://playground.devicehive.com/api/rest
+ https://playground.devicehive.com/api/rest
devicehive-ble-android
Bluetooth LE is not supported.\nApplication will close itself
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 6f4afe3..d8725e3 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,8 +1,12 @@
-