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

Dashboard and new architecture. #4

Merged
merged 17 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
6aa0bb5
Merge pull request #49 from juanpa097/feature/48-splash-screen
hpsaturn Jun 3, 2020
ad4b7c3
Merge pull request #47 from juanpa097/feature/github-templates
hpsaturn Jun 3, 2020
9bbe6bb
fix: ignored .cxx autogenerated directory
juanpa097 Jun 3, 2020
787b3a9
Merge branch 'devel' of https://github.com/juanpa097/android-hpma115s…
juanpa097 Jun 3, 2020
9ddba7a
Merge branch 'devel' of https://github.com/juanpa097/android-hpma115s…
juanpa097 Jun 3, 2020
b786ce6
Merge pull request #52 from juanpa097/feature/48-splash-screen
hpsaturn Jun 4, 2020
3ac023a
Merge pull request #53 from kike-canaries/devel
hpsaturn Jun 4, 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
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,6 @@ screenshots
store
api_aqicn.xml

# C++ generated files
app/.cxx/*

73 changes: 66 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
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"


android {
Expand Down Expand Up @@ -36,8 +41,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 @@ -55,12 +64,14 @@ dependencies {

implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.2.0-alpha06'
implementation 'com.google.android.material:material:1.3.0-alpha01'
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,15 +101,63 @@ dependencies {

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

implementation 'com.squareup.retrofit2:retrofit:2.5.0'
// 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-alpha08"

// 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.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'

// 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.2.0'
testImplementation 'androidx.test:core:1.3.0'
testImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation 'androidx.test:runner:1.2.0'
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'
}

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

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

This file was deleted.

24 changes: 12 additions & 12 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,28 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar.Launcher">
<activity android:name=".dashboard.DashboardActivity" android:theme="@style/MaterialAppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<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,6 @@
package hpsaturn.pollutionreporter.core.domain.entities

sealed class Result<out T : Any>
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,88 @@
package hpsaturn.pollutionreporter.dashboard

import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.RotateDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import dagger.hilt.android.AndroidEntryPoint
import hpsaturn.pollutionreporter.R
import hpsaturn.pollutionreporter.core.domain.entities.ErrorResult
import hpsaturn.pollutionreporter.core.domain.entities.InProgress
import hpsaturn.pollutionreporter.core.domain.entities.Success
import hpsaturn.pollutionreporter.dashboard.domain.entities.AirQualityStatus
import hpsaturn.pollutionreporter.dashboard.domain.usecases.EvaluateAirQualityStatus
import hpsaturn.pollutionreporter.dashboard.presentation.DashboardViewModel
import kotlinx.android.synthetic.main.fragment_dashboard.*
import javax.inject.Inject


@AndroidEntryPoint
class DashboardFragment : Fragment() {

@Inject
lateinit var evaluateAirQualityStatus: EvaluateAirQualityStatus

private val dashboardViewModel: DashboardViewModel by viewModels()

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
displayAirQualityIndexOnView()
displayStationDistance()
return inflater.inflate(R.layout.fragment_dashboard, container, false)
}

private fun displayAirQualityIndexOnView() {
dashboardViewModel.airQualityStatus.observe(viewLifecycleOwner, Observer {
when (it) {
is Success -> renderAqiData(it.data)
is ErrorResult -> renderError(it.exception)
is InProgress -> renderProgress()
}
})
}

private fun displayStationDistance() {
dashboardViewModel.distanceToStation.observe(viewLifecycleOwner, Observer {
currentLocationText.text = "$it Km"
})
}

private fun renderAqiData(airQualityStatus: AirQualityStatus) {
setTextVisible()
val scale = evaluateAirQualityStatus(airQualityStatus)
val background =
(airQualityIndexBar.progressDrawable as RotateDrawable).drawable as GradientDrawable
val color = ContextCompat.getColor(requireContext(), scale.colorResourceId)
background.colors =
intArrayOf(color, color) // Both the same because we don't have a gradient.
airQualityIndexText.text = "${airQualityStatus.airQualityIndex}"
airQualityLabelText.text = getString(scale.nameResourceId)
}

private fun renderError(exception: Throwable) {
setTextVisible()
airQualityIndexText.text = context?.getString(R.string.error)
airQualityLabelText.text = "${exception.message}"
}

private fun renderProgress() {
progressBar.visibility = View.VISIBLE
airQualityIndexText.visibility = View.INVISIBLE
airQualityLabelText.visibility = View.INVISIBLE
}

private fun setTextVisible() {
progressBar.visibility = View.INVISIBLE
airQualityIndexText.visibility = View.VISIBLE
airQualityLabelText.visibility = View.VISIBLE
}

}
Loading