Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 42 additions & 65 deletions app/src/main/java/com/motionapps/sensorbox/MsgListener.kt
Original file line number Diff line number Diff line change
@@ -1,82 +1,59 @@
package com.motionapps.sensorbox

import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
import com.google.android.gms.wearable.ChannelClient
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.WearableListenerService
import com.motionapps.sensorbox.activities.MainActivity
import com.motionapps.sensorbox.core.error.AppError
import com.motionapps.sensorbox.core.error.appResult
import com.motionapps.sensorbox.domain.sync.ReceiveWearFileUseCase
import com.motionapps.wearoslib.WearOsConstants.PHONE_MESSAGE_PATH
import com.motionapps.wearoslib.WearOsConstants.WEAR_STATUS
import com.motionapps.wearoslib.WearOsConstants.WEAR_SEND_SENSOR_INFO
import com.motionapps.wearoslib.WearOsConstants.WEAR_SEND_SENSOR_INFO_EXTRA
import com.motionapps.wearoslib.WearOsConstants.START_MAIN_ACTIVITY
import com.motionapps.wearoslib.WearOsConstants.WEAR_HEART_RATE_PERMISSION_REQUIRED
import com.motionapps.wearoslib.WearOsConstants.WEAR_HEART_RATE_PERMISSION_REQUIRED_BOOLEAN
import com.motionapps.wearoslib.WearOsConstants.WEAR_SEND_PATHS
import com.motionapps.wearoslib.WearOsConstants.WEAR_SEND_PATHS_EXTRA
import com.motionapps.wearoslib.WearOsConstants.WEAR_STATUS_EXTRA
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.InternalCoroutinesApi
import java.nio.charset.StandardCharsets

@InternalCoroutinesApi
@ExperimentalCoroutinesApi

/**
* Receives messages from the Wear Os
* Messages contains 2 part
* 1. part - main info, which was sent
* 2. other additional information
* these parts are divided by ;, otherwise by | in second part
* Messages are then sent as broadcasts to activities and services
*
* Suggestion - change this 2 part system to paths of the WearOs framework, meanwhile only one path is used
*/
import com.motionapps.wearoslib.protocol.WearCommand
import com.motionapps.wearoslib.protocol.WearCommandCodec
import com.motionapps.wearoslib.protocol.WearSensorCatalogStore
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class MsgListener : WearableListenerService() {
@Inject
lateinit var receiveWearFile: ReceiveWearFileUseCase

@Inject
lateinit var wearSensorCatalog: WearSensorCatalogStore

override fun onMessageReceived(messageEvent: MessageEvent) {

if (messageEvent.path == PHONE_MESSAGE_PATH) {

val data = String(messageEvent.data, StandardCharsets.UTF_8).split(";".toRegex())
private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

when (data[0]) {
WEAR_STATUS ->{ // status of the Wear os - memory status
Intent(WEAR_STATUS).also {
it.putExtra(WEAR_STATUS_EXTRA, data[1])
sendBroadcast(it)
}
}

WEAR_SEND_SENSOR_INFO ->{ // sensor info to parse for HomeFragment
Intent(WEAR_SEND_SENSOR_INFO).also {
it.putExtra(WEAR_SEND_SENSOR_INFO_EXTRA, data[1])
sendBroadcast(it)
}
override fun onMessageReceived(messageEvent: MessageEvent) {
if (messageEvent.path != PHONE_MESSAGE_PATH) return
when (val command = WearCommandCodec.decode(messageEvent.data).getOrNull()) {
WearCommand.LaunchPhone -> {
val launchIntent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}

START_MAIN_ACTIVITY -> { // shows the app
Intent(this, MainActivity::class.java).also{
it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_MULTIPLE_TASK
startActivity(it)
}
appResult(AppError.Kind.EXTERNAL_ACTION, "Launch phone app from Wear") {
startActivity(launchIntent)
}
}

WEAR_SEND_PATHS -> { // paths to synchronize between Phone and Wear Os
Intent(WEAR_SEND_PATHS).also{
it.putExtra(WEAR_SEND_PATHS_EXTRA, data[1])
sendBroadcast(it)
}
}
is WearCommand.SensorList -> wearSensorCatalog.update(command.sensors)

WEAR_HEART_RATE_PERMISSION_REQUIRED ->{
Intent(WEAR_HEART_RATE_PERMISSION_REQUIRED).also{
it.putExtra(WEAR_HEART_RATE_PERMISSION_REQUIRED_BOOLEAN, data[1] == "1")
sendBroadcast(it)
}
}
}
else -> Unit
}
}
}

override fun onChannelOpened(channel: ChannelClient.Channel) {
serviceScope.launch { receiveWearFile(channel) }
}

override fun onDestroy() {
serviceScope.cancel()
super.onDestroy()
}
}
18 changes: 6 additions & 12 deletions app/src/main/java/com/motionapps/sensorbox/SensorBoxApp.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
package com.motionapps.sensorbox

import android.app.Application
import android.content.Context
import android.os.Build
import androidx.multidex.MultiDex
import com.motionapps.sensorbox.core.error.AppDiagnostics
import dagger.hilt.android.HiltAndroidApp

/**
* building block for the Hilt dependency injection framework
*
*/
@HiltAndroidApp
class SensorBoxApp: Application(){

override fun attachBaseContext(context: Context?) {
super.attachBaseContext(context)
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
MultiDex.install(this)
}
class SensorBoxApp : Application() {
override fun onCreate() {
super.onCreate()
AppDiagnostics.install(this)
}

}
}
43 changes: 0 additions & 43 deletions app/src/main/java/com/motionapps/sensorbox/di/GpsModule.kt

This file was deleted.

This file was deleted.

This file was deleted.

28 changes: 28 additions & 0 deletions app/src/main/java/com/motionapps/sensorbox/di/PreferencesModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.motionapps.sensorbox.di

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import com.motionapps.sensorbox.core.preferences.AppPreferencesDataStoreFactory
import com.motionapps.sensorbox.core.preferences.AppPreferencesRepository
import com.motionapps.sensorbox.core.preferences.DataStoreAppPreferencesRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object PreferencesModule {
@Provides
@Singleton
fun providePreferencesDataStore(@ApplicationContext context: Context): DataStore<Preferences> =
AppPreferencesDataStoreFactory.create(context)

@Provides
@Singleton
fun providePreferencesRepository(dataStore: DataStore<Preferences>): AppPreferencesRepository =
DataStoreAppPreferencesRepository(dataStore)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.motionapps.sensorbox.domain.measurement

import android.content.Context
import android.content.Intent
import com.motionapps.sensorbox.core.storage.NativeDocumentStorage
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject

class DocumentStorageUseCase @Inject constructor(@ApplicationContext private val context: Context) {
fun hasStorage(): Result<Boolean> = NativeDocumentStorage.hasAppDirectory(context, APP_DIRECTORY)

fun displayPath(): Result<String?> = NativeDocumentStorage.displayPath(context, APP_DIRECTORY)

fun persist(resultIntent: Intent): Result<Unit> =
NativeDocumentStorage.persistRootAccess(context, resultIntent, APP_DIRECTORY)

private companion object {
const val APP_DIRECTORY = "SensorBox"
}
}
Loading