Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CanAirIO new architecture proposal #67

Open
wants to merge 43 commits into
base: new-architecture-proposal
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9bbe6bb
fix: ignored .cxx autogenerated directory
juanpa097 Jun 3, 2020
5e33494
Merge pull request #1 from juanpa097/feature/github-templates
juanpa097 Jun 3, 2020
d092735
Merge pull request #2 from juanpa097/feature/48-splash-screen
juanpa097 Jun 3, 2020
787b3a9
Merge branch 'devel' of https://github.com/juanpa097/android-hpma115s…
juanpa097 Jun 3, 2020
e21250f
Merge pull request #3 from juanpa097/feature/48-splash-screen
juanpa097 Jun 3, 2020
9ddba7a
Merge branch 'devel' of https://github.com/juanpa097/android-hpma115s…
juanpa097 Jun 3, 2020
bc787fb
feat: created material design colors and text styles
juanpa097 Jun 4, 2020
13a04ad
feat: Create dashboard layout.
juanpa097 Jun 7, 2020
69f3c1d
feat: Create bottom navigation view.
juanpa097 Jun 7, 2020
f5811d2
feat: Added support to Hilt DI and started clean architecture for das…
juanpa097 Jun 20, 2020
48bd12a
Merge branch 'feature/51-dashboard' of https://github.com/juanpa097/a…
juanpa097 Jul 2, 2020
35da248
feat: Connected the domain layer with the presentation to show the AQ…
juanpa097 Jul 23, 2020
80261db
feat: Added live location tracking and added tests for presentation l…
juanpa097 Sep 8, 2020
f20b3ba
feat: refactored live location, added color to indicate AQI status an…
juanpa097 Nov 10, 2020
61e1075
feat: refactored live location, added color to indicate AQI status an…
juanpa097 Nov 10, 2020
ce517fa
Merge branch 'feature/51-dashboard' of https://github.com/juanpa097/a…
juanpa097 Nov 10, 2020
9b4e42d
Merge pull request #4 from juanpa097/feature/51-dashboard
juanpa097 Nov 10, 2020
5a4eb34
feat: created domain layer for the reports module.
juanpa097 Nov 11, 2020
9354681
feat: added toString method to Result.
juanpa097 Nov 13, 2020
4be946e
feat: updated dependencies, added Firebase dep and provided instance …
juanpa097 Nov 13, 2020
19f4241
fix: removed irrelevant code.
juanpa097 Nov 13, 2020
d77f77b
feat: Created data layer for reports.
juanpa097 Nov 13, 2020
cbc07e2
fix: changed SensorReportInformation to data class.
juanpa097 Nov 14, 2020
8b85817
feat: Added dataBinding to build.gradle
juanpa097 Nov 14, 2020
f67e5ec
fix: Removed spacer in layout.
juanpa097 Nov 14, 2020
4deb5ea
feat: Created new fragment to replace old records list.
juanpa097 Nov 14, 2020
ce30815
feat: Added new fragment to navigation.
juanpa097 Nov 14, 2020
8f0570d
feat: Created report list adapter.
juanpa097 Nov 14, 2020
fea76e5
fix: Moved UI methods to onViewCreated in DashboardFragment.kt
juanpa097 Nov 18, 2020
fc797cc
fix: Fixed format.
juanpa097 Nov 18, 2020
5e87176
feat: Fixed Firebase models and fixed data layer to map correctly the…
juanpa097 Nov 18, 2020
7d736ad
fix: Navigation to navigate to the new reports fragment.
juanpa097 Nov 18, 2020
116da18
feat: Added list to reports fragment.
juanpa097 Nov 18, 2020
fdb0cac
feat: Added strings, list item dimension and top bar style.
juanpa097 Dec 2, 2020
196745a
fix: removed unfeasible test.
juanpa097 Dec 2, 2020
739bcf9
fix: added SuppressLint to hard coded string.
juanpa097 Dec 2, 2020
e031a78
feat: Created new UI for report information item.
juanpa097 Dec 2, 2020
6b4a055
fix: removed hard coded strings and fixed spelling.
juanpa097 Dec 2, 2020
3b27e7d
fix: Updated old ViewHolders with new views ids.
juanpa097 Dec 3, 2020
231ccd3
fix: Renamed files to OpenSensorReports* inorder to leave room to sca…
juanpa097 Dec 3, 2020
9a27813
fix: Added spinner to public records list.
juanpa097 Dec 3, 2020
40116ff
Merge pull request #5 from juanpa097/feature/reports-refactor
juanpa097 Dec 3, 2020
5e83966
Merge branch 'new-architecture-proposal' into devel
hpsaturn Jun 28, 2021
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ screenshots
store
api_aqicn.xml

# C++ generated files
app/.cxx/*
app/.cxx
mainframer
remoteAssemble
Expand Down
87 changes: 83 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
apply plugin: 'com.android.application'
apply plugin: 'com.livinglifetechway.quickpermissions_plugin'
apply plugin: 'io.fabric'
apply plugin: "kotlin-android"
apply plugin: "kotlin-android-extensions"
apply plugin: "kotlin-kapt"
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: "de.mannodermaus.android-junit5"
apply plugin: 'com.google.firebase.crashlytics'


android {
compileSdkVersion project.mCompileSdkVersion.toInteger()
defaultConfig {
Expand All @@ -16,6 +24,7 @@ android {
}
}
}
buildFeatures { dataBinding = true }
buildTypes {
release {
minifyEnabled false
Expand All @@ -34,8 +43,12 @@ android {
}
}
compileOptions {
targetCompatibility 1.8
sourceCompatibility 1.8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}

testOptions {
Expand All @@ -54,13 +67,17 @@ dependencies {
implementation 'com.karumi:dexter:6.2.1'

implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0
implementation 'com.google.android.material:material:1.3.0-alpha01'
implementation 'com.google.android.material:material:1.3.0'

implementation "androidx.preference:preference:1.1.1"
implementation 'com.takisoft.preferencex:preferencex:1.1.0-alpha05'
implementation 'androidx.multidex:multidex:2.0.1'

implementation 'com.jakewharton:butterknife:10.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0'

implementation 'com.jakewharton.rxbinding2:rxbinding:2.2.0'
Expand Down Expand Up @@ -90,6 +107,66 @@ dependencies {

implementation 'com.github.vic797:prowebview:2.2.1'

// Firebase
implementation platform('com.google.firebase:firebase-bom:26.0.0')
implementation 'com.google.firebase:firebase-database-ktx'

// Dexter Permissions Requesting
implementation 'com.karumi:dexter:6.2.1'

// Android KTX
implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.activity:activity-ktx:1.1.0"
implementation "androidx.fragment:fragment:1.3.0-beta01"

// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

// Debug Retrofit
implementation("com.squareup.okhttp3:logging-interceptor:4.7.2")

// Hilt
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"

// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"

// Jetpack Navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'

// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.7'

// Junit 5
testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.6.2"

// Mockk
testImplementation "io.mockk:mockk:1.10.0"

// OkHttp Mock Web Server
testImplementation "com.squareup.okhttp3:mockwebserver:4.7.2"

testImplementation 'junit:junit:4.12'
testImplementation 'androidx.test:core:1.3.0'
testImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "android.arch.core:core-testing:1.1.1"
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

implementation 'com.android.support:design:28.0.0'

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

Expand All @@ -98,7 +175,9 @@ dependencies {
testImplementation 'org.mockito:mockito-core:3.3.3'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

apply plugin: 'com.google.gms.google-services'

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

This file was deleted.

20 changes: 12 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".dashboard.DashboardActivity" android:theme="@style/MaterialAppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
Expand All @@ -33,18 +34,21 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar.Launcher">
</activity>

<service
android:name=".service.RecordTrackService"
android:enabled="true"
android:exported="true" />

<!--<receiver android:name=".bleservice.ServiceScheduler">-->
<!--<intent-filter>-->
<!--<action android:name="android.intent.action.BOOT_COMPLETED" />-->
<!--</intent-filter>-->
<!--</receiver>-->
android:exported="true" /> <!-- <receiver android:name=".bleservice.ServiceScheduler"> -->
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.BOOT_COMPLETED" /> -->
<!-- </intent-filter> -->
<!-- </receiver> -->
<receiver android:name=".service.RecordTrackReceiver" />

</application>

</manifest>
3 changes: 3 additions & 0 deletions app/src/main/java/hpsaturn/pollutionreporter/AppData.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
import com.polidea.rxandroidble2.RxBleClient;
import com.polidea.rxandroidble2.internal.RxBleLog;

import dagger.hilt.android.HiltAndroidApp;
import hpsaturn.pollutionreporter.api.AqicnApiManager;

/**
* Created by Antonio Vanegas @hpsaturn on 6/13/18.
*/

@HiltAndroidApp
public class AppData extends MultiDexApplication{

private RxBleClient rxBleClient;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package hpsaturn.pollutionreporter.core.data.mappers

interface Mapper<I, O> {
operator fun invoke(input: I): O
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package hpsaturn.pollutionreporter.core.domain.entities

sealed class Result<out T : Any> {
override fun toString(): String = when (this) {
is Success<*> -> "Success[data=$data]"
is ErrorResult -> "Error[exception=$exception]"
InProgress -> "Loading"
}
}

data class Success<out T : Any>(val data: T) : Result<T>()
data class ErrorResult(val exception: Throwable) : Result<Nothing>()
object InProgress : Result<Nothing>()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package hpsaturn.pollutionreporter.core.domain.errors

class ServerException(message: String = "") : Exception(message)
class PermissionException(message: String = "") : Exception(message)
class PermissionNotGrantedException(message: String = "") : Exception(message)
class ConnectionException(message: String = "") : Exception(message)
class UnexpectedException(message: String = "") : Exception(message)
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package hpsaturn.pollutionreporter.dashboard

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.setupWithNavController
import com.hpsaturn.tools.Logger
import dagger.hilt.android.AndroidEntryPoint
import hpsaturn.pollutionreporter.BaseActivity
import hpsaturn.pollutionreporter.Config
import hpsaturn.pollutionreporter.R
import hpsaturn.pollutionreporter.service.RecordTrackScheduler
import hpsaturn.pollutionreporter.service.RecordTrackService
import kotlinx.android.synthetic.main.activity_dashboard.*

private val TAG = DashboardActivity::class.java.simpleName

@AndroidEntryPoint
class DashboardActivity : AppCompatActivity() {


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)

setupNavigationComponent()
startRecordTrackService()
checkBluetoothSupport()
}

/**
* Sets up the app to use Android Navigation Component. More information of this component can
* be found here: https://developer.android.com/guide/navigation/navigation-getting-started
*/
private fun setupNavigationComponent() {
val navController = findNavController(R.id.nav_host_fragment)
bottomNavigation.setupWithNavController(navController)
}

private fun startRecordTrackService() {
Log.i(TAG, "starting RecordTrackService..")
val trackServiceIntent = Intent(this, RecordTrackService::class.java)
startService(trackServiceIntent)
RecordTrackScheduler.startScheduleService(this, Config.DEFAULT_INTERVAL)
}


// TODO (@juanpa097) - The code bellow this comment should be refactor.

private fun checkBluetoothSupport() { // Use this check to determine whether BLE is supported on the device.
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val mBluetoothAdapter = bluetoothManager.adapter
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show()
} else if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, 0)
} else Logger.i(BaseActivity.TAG, "[BLE] checkBluetoohtBle: ready!")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package hpsaturn.pollutionreporter.dashboard

import android.location.Location
import androidx.lifecycle.LiveData
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import hpsaturn.pollutionreporter.core.data.mappers.Mapper
import hpsaturn.pollutionreporter.core.domain.entities.Result
import hpsaturn.pollutionreporter.dashboard.data.mappers.AirQualityStatusMapper
import hpsaturn.pollutionreporter.dashboard.data.models.AqicnFeedResponse
import hpsaturn.pollutionreporter.dashboard.data.repositories.AirQualityStatusRepositoryImpl
import hpsaturn.pollutionreporter.dashboard.data.services.AqicnApiFeedService
import hpsaturn.pollutionreporter.dashboard.domain.entities.AirQualityStatus
import hpsaturn.pollutionreporter.dashboard.domain.repositories.AirQualityStatusRepository
import hpsaturn.pollutionreporter.dashboard.presentation.CurrentLocationLiveData
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(ApplicationComponent::class)
abstract class DashboardModule {

@Binds
abstract fun bindAirQualityStatusMapper(airQualityStatusMapper: AirQualityStatusMapper):
Mapper<AqicnFeedResponse, AirQualityStatus>

@Binds
abstract fun bindAirQualityStatusRepositoryImpl(
airQualityStatusRepositoryImpl: AirQualityStatusRepositoryImpl
): AirQualityStatusRepository

@Binds
abstract fun bindCurrentLocationLiveData(currentLocationLiveData: CurrentLocationLiveData):
LiveData<Result<Location>>

companion object {
@Singleton
@Provides
fun provideAqicnApiFeedService(retrofit: Retrofit): AqicnApiFeedService =
retrofit.create(AqicnApiFeedService::class.java)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package hpsaturn.pollutionreporter.dashboard.data.mappers

import hpsaturn.pollutionreporter.core.data.mappers.Mapper
import hpsaturn.pollutionreporter.dashboard.data.models.AqicnFeedResponse
import hpsaturn.pollutionreporter.dashboard.domain.entities.AirQualityStatus
import javax.inject.Inject

class AirQualityStatusMapper @Inject constructor() : Mapper<AqicnFeedResponse, AirQualityStatus> {
override fun invoke(input: AqicnFeedResponse): AirQualityStatus = AirQualityStatus(
input.data.aqi,
input.data.city.name,
input.data.city.geo[0],
input.data.city.geo[1]
)
}
Loading