From e8a052fd2c03b399550b6c9be3199d35fdd47f10 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sat, 3 Jan 2015 22:49:58 +0100 Subject: o Adding a database of BT devices and soil devices, sensors and samples. --- app/app.iml | 2 + app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 7 +- .../assets/db/migration/bt/V001.001__baseline.sql | 8 ++ .../db/migration/sm/V001.001__sm_baseline.sql | 8 ++ .../assets/db/migration/sm/V001.002__sample.sql | 5 + .../main/java/io/trygvis/android/bt/BtDevice.java | 41 ++++++-- .../main/java/io/trygvis/android/bt/BtService.java | 8 +- .../io/trygvis/android/bt/DefaultBtService.java | 109 +++++++++++++++++++-- 9 files changed, 173 insertions(+), 17 deletions(-) create mode 100644 app/src/main/assets/db/migration/bt/V001.001__baseline.sql create mode 100644 app/src/main/assets/db/migration/sm/V001.001__sm_baseline.sql create mode 100644 app/src/main/assets/db/migration/sm/V001.002__sample.sql diff --git a/app/app.iml b/app/app.iml index eaea10c..7b810b7 100644 --- a/app/app.iml +++ b/app/app.iml @@ -86,7 +86,9 @@ + + diff --git a/app/build.gradle b/app/build.gradle index 320e9a4..9df79ba 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,5 +46,7 @@ dependencies { compile('com.crashlytics.sdk.android:crashlytics:2.1.0@aar') { transitive = true; } + compile 'org.sqldroid:sqldroid:1.0.3' + compile 'org.flywaydb:flyway-core:3.1' // compile 'net.sourceforge.streamsupport:streamsupport:1.1.2' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 85d6d39..91cd1b2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,7 +39,12 @@ + android:enabled="true" + android:exported="false"> + + { +public class BtDevice> { private final static String TAG = BtDevice.class.getSimpleName(); private final DefaultBtService btService; @@ -14,18 +14,31 @@ public class BtDevice { private BtScanResult scanResult; private A tag; - private boolean seenNow; + private final long id; + private final boolean seenBefore; + private final Date firstSeen; + private Date lastSeen; - public static interface BtDeviceWrapper { + public static interface BtDeviceWrapper> { BtDevice getBtDevice(); } - BtDevice(DefaultBtService btService, BluetoothDevice bluetoothDevice, Function, A> tagConstructor, Integer rssi, BtScanResult scanResult) { + BtDevice(DefaultBtService btService, BluetoothDevice bluetoothDevice, + BtService.BtDbIntegration btDbIntegration, long id, Integer rssi, + BtScanResult scanResult, boolean seenBefore, Date firstSeen, Date lastSeen) { this.btService = btService; this.bluetoothDevice = bluetoothDevice; - this.tag = tagConstructor.apply(this); + this.tag = btDbIntegration.createTag(this); + this.id = id; this.rssi = rssi; this.scanResult = scanResult; + this.seenBefore = seenBefore; + this.firstSeen = firstSeen; + this.lastSeen = lastSeen; + } + + public long getId() { + return id; } public A getTag() { @@ -44,6 +57,22 @@ public class BtDevice { return rssi; } + public boolean isSeenBefore() { + return seenBefore; + } + + public Date getFirstSeen() { + return firstSeen; + } + + public Date getLastSeen() { + return lastSeen; + } + + public void setLastSeen(Date lastSeen) { + this.lastSeen = lastSeen; + } + public boolean connect(BtActionExecutor executor) { Log.i(TAG, "connect(), address=" + bluetoothDevice.getAddress() + ", queue=" + executor); bluetoothDevice.connectGatt(btService, false, executor.asCallback()); diff --git a/app/src/main/java/io/trygvis/android/bt/BtService.java b/app/src/main/java/io/trygvis/android/bt/BtService.java index 968a4a8..ca8bcd9 100644 --- a/app/src/main/java/io/trygvis/android/bt/BtService.java +++ b/app/src/main/java/io/trygvis/android/bt/BtService.java @@ -7,11 +7,9 @@ import android.content.IntentFilter; import java.util.Collection; -import io.trygvis.android.Function; - public interface BtService> { - boolean initialize(Function, A> tagConstructor); + boolean initialize(BtDbIntegration btDbIntegration); void clearCache(); @@ -29,6 +27,10 @@ public interface BtService> { Collection getTags(); + public static interface BtDbIntegration> { + A createTag(BtDevice a); + } + public static class BtServiceListenerBroadcastReceiver extends BroadcastReceiver { public static final String INTENT_NAME = BtServiceListenerBroadcastReceiver.class.getName(); diff --git a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java index 51d84af..5e13a1f 100644 --- a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java +++ b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java @@ -4,20 +4,28 @@ import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; +import android.content.ComponentName; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.util.Log; import android.widget.Toast; +import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.android.ContextHolder; + import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.Set; -import io.trygvis.android.Function; import io.trygvis.android.LocalBinder; import io.trygvis.soilmoisture.R; @@ -34,7 +42,7 @@ public class DefaultBtService> extends Ser // State // ----------------------------------------------------------------------- - private Function, A> tagConstructor; + private BtDbIntegration btDbIntegration; private BluetoothManager bluetoothManager; @@ -49,13 +57,13 @@ public class DefaultBtService> extends Ser // ----------------------------------------------------------------------- @Override - public boolean initialize(Function, A> tagConstructor) { + public boolean initialize(BtDbIntegration btDbIntegration) { if (bluetoothManager != null) { Log.i(TAG, "Already initialized"); return false; } - this.tagConstructor = tagConstructor; + this.btDbIntegration = btDbIntegration; // Use this check to determine whether BLE is supported on the device. Then you can // selectively disable BLE-related features. @@ -171,19 +179,106 @@ public class DefaultBtService> extends Ser return binder; } + @Override + public void onCreate() { + Bundle data; + + try { + ComponentName myService = new ComponentName(this, this.getClass()); + data = getPackageManager().getServiceInfo(myService, PackageManager.GET_META_DATA).metaData; + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException(e); + } + + SQLiteDatabase db = openBtDevices(); + String path; + try { + path = db.getPath(); + } finally { + db.close(); + } + + { + ContextHolder.setContext(this); + Flyway flyway = new Flyway(); + flyway.setDataSource("jdbc:sqlite:" + path, "", ""); + flyway.setTable("schema_version_bt"); + flyway.setLocations("db/migration/bt"); + + flyway.migrate(); + } + + String customMigrations = data.getString(getClass().getName() + ".migration", null); + + if (customMigrations != null) { + ContextHolder.setContext(this); + Flyway flyway = new Flyway(); + flyway.setDataSource("jdbc:sqlite:" + path, "", ""); + flyway.setTable("schema_version_custom"); + flyway.setLocations(customMigrations); + + flyway.setBaselineOnMigrate(true); + flyway.migrate(); + } + } + // ----------------------------------------------------------------------- // Stuff // ----------------------------------------------------------------------- + private SQLiteDatabase openBtDevices() { + return openOrCreateDatabase("bt-devices", MODE_ENABLE_WRITE_AHEAD_LOGGING, null); + } + private BtDevice register(BluetoothDevice bluetoothDevice, Integer rssi, BtScanResult scanResult) { - BtDevice btDevice = findDevice(bluetoothDevice.getAddress()); + String address = bluetoothDevice.getAddress(); + BtDevice btDevice = findDevice(address); if (btDevice != null) { return btDevice; } - Log.i(TAG, "New device: " + bluetoothDevice.getAddress()); - btDevice = new BtDevice<>(this, bluetoothDevice, tagConstructor, rssi, scanResult); + long now = System.currentTimeMillis(); + + SQLiteDatabase db = openBtDevices(); + try { + db.beginTransaction(); + + Cursor cursor = db.query("bt_device", new String[]{"id", "first_seen"}, "address=?", + new String[]{address}, null, null, null); + + long id; + Date firstSeen, lastSeen; + boolean seenBefore = cursor.moveToNext(); + + if (seenBefore) { + id = cursor.getLong(0); + firstSeen = new Date(cursor.getLong(1)); + lastSeen = new Date(now); + + ContentValues values = new ContentValues(); + values.put("last_seen", now); + db.update("bt_device", values, "address=?", new String[]{address}); + } else { + ContentValues values = new ContentValues(); + values.put("address", address); + values.put("first_seen", now); + values.put("last_seen", now); + id = db.insert("bt_device", null, values); + firstSeen = lastSeen = new Date(now); + } + + Log.i(TAG, "New device: " + address + ", seenBefore=" + seenBefore); + btDevice = new BtDevice<>(this, bluetoothDevice, btDbIntegration, id, rssi, scanResult, + seenBefore, firstSeen, lastSeen); + + cursor.close(); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + db.close(); + } + devices.add(btDevice); sendBroadcast(createNewDevice(btDevice.getAddress())); -- cgit v1.2.3