Browse Source

Migrate to androidx & add ActivityRecognition

androidx-act-recog
sipp11 5 years ago
parent
commit
bacb8b9110
  1. 2
      .idea/misc.xml
  2. 43
      app/build.gradle
  3. 14
      app/src/androidTest/java/co/zzyzx/sensorlogger/DatabaseTest.kt
  4. 9
      app/src/androidTest/java/co/zzyzx/sensorlogger/ExampleInstrumentedTest.kt
  5. 38
      app/src/main/AndroidManifest.xml
  6. 44
      app/src/main/java/co/zzyzx/sensorlogger/EndlessService.kt
  7. 7
      app/src/main/java/co/zzyzx/sensorlogger/MainActivity.kt
  8. 8
      app/src/main/java/co/zzyzx/sensorlogger/db/Database.kt
  9. 4
      app/src/main/java/co/zzyzx/sensorlogger/db/dao.kt
  10. 8
      app/src/main/java/co/zzyzx/sensorlogger/db/entity.kt

2
.idea/misc.xml

@ -5,7 +5,7 @@
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" /> <configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations> </configurations>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

43
app/build.gradle

@ -12,7 +12,11 @@ android {
targetSdkVersion 28 targetSdkVersion 28
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
} }
buildTypes { buildTypes {
release { release {
@ -20,29 +24,44 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
// Gradle automatically adds 'android.test.runner' as a dependency.
// useLibrary 'android.test.runner'
// useLibrary 'android.test.base'
// useLibrary 'android.test.mock'
//
// testOptions {
// execution 'ANDROIDX_TEST_ORCHESTRATOR'
// }
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3' // implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.github.kittinunf.fuel:fuel:2.1.0' implementation 'com.github.kittinunf.fuel:fuel:2.1.0'
implementation 'com.github.kittinunf.fuel:fuel-android:2.1.0' implementation 'com.github.kittinunf.fuel:fuel-android:2.1.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-M2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-M2'
// Room dependencies // Room dependencies
// implementation 'androidx.room:room-runtime:2.0.0' implementation 'androidx.room:room-runtime:2.1.0'
// kapt 'androidx.room:room-compiler:2.0.0' kapt 'androidx.room:room-compiler:2.1.0'
implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
kapt 'android.arch.persistence.room:compiler:1.1.1'
// activity recognition
implementation 'com.google.android.gms:play-services-location:17.0.0'
implementation 'com.opencsv:opencsv:4.0' implementation 'com.opencsv:opencsv:4.0'
// implementation 'android.arch.lifecycle:excompile 'com.opencsv:opencsv:4.0'tensions:1.1.1'
// kapt 'android.arch.lifecycle:compiler:1.1.1'
// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// Core library
androidTestImplementation 'androidx.test:core:1.2.0'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
// Assertions
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
} }

14
app/src/androidTest/java/co/zzyzx/sensorlogger/DatabaseTest.kt

@ -1,9 +1,9 @@
package co.zzyzx.sensorlogger package co.zzyzx.sensorlogger
import android.arch.persistence.room.Room import androidx.room.Room
import android.support.test.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4
import android.support.test.runner.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry
import co.zzyzx.sensorlogger.db.AppDatabase import co.zzyzx.sensorlogger.db.AppDatabase
import co.zzyzx.sensorlogger.db.Record import co.zzyzx.sensorlogger.db.Record
import co.zzyzx.sensorlogger.db.RecordDao import co.zzyzx.sensorlogger.db.RecordDao
@ -23,7 +23,7 @@ class DatabaseTest {
@Before @Before
fun createDb() { fun createDb() {
val appContext = InstrumentationRegistry.getTargetContext() val appContext = InstrumentationRegistry.getInstrumentation().targetContext
db = Room.inMemoryDatabaseBuilder(appContext, AppDatabase::class.java) db = Room.inMemoryDatabaseBuilder(appContext, AppDatabase::class.java)
.allowMainThreadQueries() .allowMainThreadQueries()
.build() .build()
@ -41,9 +41,7 @@ class DatabaseTest {
data = "123,23232" data = "123,23232"
) )
) )
for (rec in records) { recordDao.insert(*records.toTypedArray())
recordDao.insertAll(rec)
}
} }
@After @After
@ -61,7 +59,7 @@ class DatabaseTest {
sensor = "gps", sensor = "gps",
data = "333,32322" data = "333,32322"
) )
recordDao.insertAll(rec) recordDao.insert(rec)
val byName = recordDao.findBySensor("gps") val byName = recordDao.findBySensor("gps")
assertEquals(byName.data, rec.data) assertEquals(byName.data, rec.data)
assertEquals(byName.timestamp, rec.timestamp) assertEquals(byName.timestamp, rec.timestamp)

9
app/src/androidTest/java/co/zzyzx/sensorlogger/ExampleInstrumentedTest.kt

@ -1,13 +1,12 @@
package co.zzyzx.sensorlogger package co.zzyzx.sensorlogger
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.junit.Assert.*
/** /**
* Instrumented test, which will execute on an Android device. * Instrumented test, which will execute on an Android device.
* *
@ -18,7 +17,7 @@ class ExampleInstrumentedTest {
@Test @Test
fun useAppContext() { fun useAppContext() {
// Context of the app under test. // Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext() val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("co.zzyzx.sensorlogger", appContext.packageName) assertEquals("co.zzyzx.sensorlogger", appContext.packageName)
} }
} }

38
app/src/main/AndroidManifest.xml

@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.zzyzx.sensorlogger"> package="co.zzyzx.sensorlogger">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application <application
@ -20,21 +22,37 @@
<service <service
android:name=".EndlessService" android:name=".EndlessService"
android:enabled="true" android:enabled="true"
android:exported="false"> android:exported="false"></service>
</service>
<activity android:name=".MainActivity"> <activity android:name=".MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<receiver android:enabled="true" android:name=".StartReceiver"> <receiver
android:name=".StartReceiver"
android:enabled="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- You don't need to include android:required="false" if your app's
minSdkVersion is 28 or higher. -->
<uses-library
android:name="android.test.runner"
android:required="false" />
<!-- For both of these declarations, you don't need to include
android:required="false" if your app's minSdkVersion is 28
or higher. -->
<uses-library
android:name="android.test.base"
android:required="false" />
<uses-library
android:name="android.test.mock"
android:required="false" />
</application> </application>

44
app/src/main/java/co/zzyzx/sensorlogger/EndlessService.kt

@ -21,6 +21,7 @@ import android.widget.Toast
import co.zzyzx.sensorlogger.db.Record import co.zzyzx.sensorlogger.db.Record
import co.zzyzx.sensorlogger.db.RecordRepository import co.zzyzx.sensorlogger.db.RecordRepository
import com.github.kittinunf.fuel.Fuel import com.github.kittinunf.fuel.Fuel
import com.google.android.gms.location.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
@ -39,6 +40,7 @@ class EndlessService : Service(), SensorEventListener, LocationListener {
private val notificationChannelId = "ENDLESS SERVICE CHANNEL" private val notificationChannelId = "ENDLESS SERVICE CHANNEL"
private val notificationId = 1011 private val notificationId = 1011
private lateinit var mActivityRecognitionClient: ActivityRecognitionClient
private lateinit var mSensorManager: SensorManager private lateinit var mSensorManager: SensorManager
private lateinit var mAccelerometer: Sensor private lateinit var mAccelerometer: Sensor
private lateinit var mGyroscope: Sensor private lateinit var mGyroscope: Sensor
@ -78,10 +80,8 @@ class EndlessService : Service(), SensorEventListener, LocationListener {
"with a null intent. It has been probably restarted by the system." "with a null intent. It has been probably restarted by the system."
) )
} }
mSensorManager.registerListener(this, mAccelerometer, SENSOR_DELAY) mSensorManager.registerListener(this, mAccelerometer, SENSOR_DELAY)
mSensorManager.registerListener(this, mGyroscope, SENSOR_DELAY) mSensorManager.registerListener(this, mGyroscope, SENSOR_DELAY)
// by returning this we make sure the service is restarted if the system kills the service // by returning this we make sure the service is restarted if the system kills the service
return START_STICKY return START_STICKY
} }
@ -100,6 +100,7 @@ class EndlessService : Service(), SensorEventListener, LocationListener {
mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
setupActivityRecognitionUpdates()
if (checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager mLocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
@ -119,6 +120,45 @@ class EndlessService : Service(), SensorEventListener, LocationListener {
} }
} }
private fun setupActivityRecognitionUpdates() {
// ActivityRecognition
val transitions = mutableListOf<ActivityTransition>()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.ON_BICYCLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.ON_BICYCLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build()
val request = ActivityTransitionRequest(transitions)
mActivityRecognitionClient = ActivityRecognition.getClient(applicationContext)
mActivityRecognitionClient.requestActivityTransitionUpdates(request, null)
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
mSensorManager.unregisterListener(this) mSensorManager.unregisterListener(this)

7
app/src/main/java/co/zzyzx/sensorlogger/MainActivity.kt

@ -10,11 +10,12 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.os.Handler import android.os.Handler
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import co.zzyzx.sensorlogger.db.RecordRepository import co.zzyzx.sensorlogger.db.RecordRepository
import com.opencsv.CSVWriter import com.opencsv.CSVWriter
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*

8
app/src/main/java/co/zzyzx/sensorlogger/db/Database.kt

@ -1,15 +1,15 @@
package co.zzyzx.sensorlogger.db package co.zzyzx.sensorlogger.db
import android.arch.persistence.room.Database
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import android.content.Context import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.time.Instant import java.time.Instant
@Database(entities = arrayOf(Record::class), version = 1, exportSchema = false) @Database(entities = [Record::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
abstract fun recordDao(): RecordDao abstract fun recordDao(): RecordDao
} }

4
app/src/main/java/co/zzyzx/sensorlogger/db/dao.kt

@ -1,7 +1,7 @@
package co.zzyzx.sensorlogger.db package co.zzyzx.sensorlogger.db
import android.arch.lifecycle.LiveData import androidx.lifecycle.LiveData
import android.arch.persistence.room.* import androidx.room.*
@Dao @Dao

8
app/src/main/java/co/zzyzx/sensorlogger/db/entity.kt

@ -1,9 +1,9 @@
package co.zzyzx.sensorlogger.db package co.zzyzx.sensorlogger.db
import android.arch.persistence.room.ColumnInfo import androidx.room.ColumnInfo
import android.arch.persistence.room.Entity import androidx.room.Entity
import android.arch.persistence.room.Index import androidx.room.Index
import android.arch.persistence.room.PrimaryKey import androidx.room.PrimaryKey
@Entity(indices = [(Index(value = ["timestamp", "sensor"], unique = true))]) @Entity(indices = [(Index(value = ["timestamp", "sensor"], unique = true))])

Loading…
Cancel
Save