Skip to content

Commit 46b8a77

Browse files
committed
Use Firebase for settings
- Commute home and work address, travel mode - Compact UI configuration Also upgrading dependencies and using Java 8 features
1 parent 7ba09b4 commit 46b8a77

File tree

16 files changed

+374
-129
lines changed

16 files changed

+374
-129
lines changed

README.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,35 @@
11
# Smart Mirror
22

3-
This is the source code for the prototype UI of my smart mirror projects outlined in [this article](https://medium.com/@maxbraun/my-bathroom-mirror-is-smarter-than-yours-94b21c6671ba) and its [follow-up](https://medium.com/@maxbraun/smarter-mirrors-and-how-theyre-made-327997b9eff7).
4-
5-
[!["Smart Mirror"](mirror.jpg)](https://medium.com/@maxbraun/my-bathroom-mirror-is-smarter-than-yours-94b21c6671ba#.4exmyxt0w)
6-
7-
Simply import the whole project into [Android Studio](http://developer.android.com/tools/studio/index.html), then build and run the apk. The first prototype uses [`HomeActivity.java`](app/src/main/java/net/maxbraun/mirror/HomeActivity.java) and the second one uses [`CompactHomeActivity.java`](app/src/main/java/net/maxbraun/mirror/CompactHomeActivity.java).
8-
9-
While the time, date, and news show up without any additional changes, you need to first enable the respective APIs in order to see the weather, commute, and body measures. Edit [`keys.xml`](app/src/main/res/values/keys.xml) and enter the key for the [Dark Sky API](https://darksky.net/dev/), the key for the [Google Maps Directions API](https://developers.google.com/maps/documentation/directions/start), and multiple keys for the [Nokia Health API](https://developer.health.nokia.com/oauth2/). The home and work addresses for the commute need to be entered in [`commute.xml`](app/src/main/res/values/commute.xml).
3+
This is the source code for the prototype UI of my smart mirror projects outlined in
4+
[this article](https://medium.com/@maxbraun/my-bathroom-mirror-is-smarter-than-yours-94b21c6671ba)
5+
and its [follow-up](https://medium.com/@maxbraun/smarter-mirrors-and-how-theyre-made-327997b9eff7).
6+
7+
[![Smart Mirror 1](mirror-1.jpg)](https://medium.com/@maxbraun/my-bathroom-mirror-is-smarter-than-yours-94b21c6671ba)
8+
9+
[![Smart Mirror 2](mirror-2.jpg)](https://medium.com/@maxbraun/smarter-mirrors-and-how-theyre-made-327997b9eff7)
10+
11+
To get started, import the whole project into
12+
[Android Studio](http://developer.android.com/tools/studio/index.html), then build and run the apk.
13+
The first prototype uses
14+
[`HomeActivity.java`](app/src/main/java/net/maxbraun/mirror/HomeActivity.java) and the second one
15+
uses [`CompactHomeActivity.java`](app/src/main/java/net/maxbraun/mirror/CompactHomeActivity.java).
16+
17+
While the time, date, and news show up without any additional changes, you need to first enable the
18+
respective APIs in order to see the weather, commute, and body measures. Edit
19+
[`keys.xml`](app/src/main/res/values/keys.xml) and enter the key for the
20+
[Dark Sky API](https://darksky.net/dev/), the key for the
21+
[Google Maps Directions API](https://developers.google.com/maps/documentation/directions/start), and
22+
multiple keys for the [Nokia Health API](https://developer.health.nokia.com/oauth2/).
23+
24+
The home and work addresses and the travel mode for the commute are pulled from a
25+
[Firebase Realtime Database](https://firebase.google.com/docs/database/) and can be edited in the
26+
[Firebase Console](https://console.firebase.google.com/) after
27+
[adding Firebase to your Android Studio project](https://firebase.google.com/docs/android/setup).
28+
The client expects a `commute_settings` path with string children `home`, `work`, and `travel_mode`.
29+
The composition of the [compact UI](app/src/main/java/net/maxbraun/mirror/CompactHomeActivity.java)
30+
is also configured via the Firebase Database: The `compact_ui_settings` path has boolean children
31+
for `body`, `commute`, `time`, and `weather` that determine which ones are shown. See
32+
[`database-example.json`](database-example.json) for a sample layout.
1033

1134
## License
1235

app/app.iml

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,21 @@
2222
</configuration>
2323
</facet>
2424
</component>
25-
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
26-
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
27-
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
25+
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
26+
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
27+
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
2828
<exclude-output />
2929
<content url="file://$MODULE_DIR$">
3030
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
31-
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
31+
<sourceFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources/debug/processDebugResources/r" isTestSource="false" generated="true" />
3232
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
3333
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
3434
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
35+
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/google-services/debug" type="java-resource" />
3536
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
3637
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
3738
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
38-
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
39+
<sourceFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources/debugAndroidTest/processDebugAndroidTestResources/r" isTestSource="true" generated="true" />
3940
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
4041
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
4142
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
@@ -84,43 +85,62 @@
8485
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
8586
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
8687
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
87-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
88+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
89+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/apk_list" />
8890
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
8991
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/build-info" />
9092
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
93+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-libraries" />
9194
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
92-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
95+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/checkDebugClasspath" />
96+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/compatible_screen_manifest" />
9397
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
9498
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
9599
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
96100
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
97101
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-apk" />
98102
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" />
99-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" />
103+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_merged_manifests" />
104+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_split_apk_resources" />
105+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
100106
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
101-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
102107
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
103-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
108+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" />
109+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
104110
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
111+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" />
105112
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
106113
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
107114
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
108115
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
116+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
109117
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
110118
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
111-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" />
119+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split_list" />
112120
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
113121
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
114122
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
115123
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
116124
</content>
117-
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
125+
<orderEntry type="jdk" jdkName="Android API 26 Platform" jdkType="Android SDK" />
118126
<orderEntry type="sourceFolder" forTests="false" />
119-
<orderEntry type="library" name="Gradle: com.android.support:support-v4-23.4.0" level="project" />
120-
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:23.4.0@jar" level="project" />
121-
<orderEntry type="library" name="Gradle: com.android.support:recyclerview-v7-23.4.0" level="project" />
127+
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-base-16.0.1" level="project" />
128+
<orderEntry type="library" name="Gradle: com.google.firebase:firebase-database-collection-16.0.1" level="project" />
129+
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-tasks-16.0.1" level="project" />
130+
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.0.0@jar" level="project" />
131+
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui-26.1.0" level="project" />
132+
<orderEntry type="library" name="Gradle: com.google.firebase:firebase-common-16.0.4" level="project" />
133+
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils-26.1.0" level="project" />
134+
<orderEntry type="library" name="Gradle: com.android.support:support-fragment-26.1.0" level="project" />
135+
<orderEntry type="library" name="Gradle: android.arch.core:common:1.0.0@jar" level="project" />
136+
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-basement-16.0.1" level="project" />
122137
<orderEntry type="library" name="Gradle: com.github.scribejava:scribejava-apis:5.5.0@jar" level="project" />
123138
<orderEntry type="library" name="Gradle: com.github.scribejava:scribejava-core:5.5.0@jar" level="project" />
124-
<orderEntry type="library" name="Gradle: com.android.support:leanback-v17-23.4.0" level="project" />
139+
<orderEntry type="library" name="Gradle: com.android.support:support-media-compat-26.1.0" level="project" />
140+
<orderEntry type="library" name="Gradle: com.google.firebase:firebase-database-16.0.5" level="project" />
141+
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:26.1.0@jar" level="project" />
142+
<orderEntry type="library" name="Gradle: com.android.support:support-compat-26.1.0" level="project" />
143+
<orderEntry type="library" name="Gradle: com.android.support:support-v4-26.1.0" level="project" />
144+
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.0.0" level="project" />
125145
</component>
126146
</module>

app/build.gradle

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
apply plugin: 'com.android.application'
22

33
android {
4-
compileSdkVersion 23
4+
compileSdkVersion 26
55
defaultConfig {
66
applicationId "net.maxbraun.mirror"
77
minSdkVersion 22
8-
targetSdkVersion 22
8+
targetSdkVersion 26
99
versionCode 1
1010
versionName "1.0"
1111
}
@@ -15,10 +15,16 @@ android {
1515
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
1616
}
1717
}
18+
compileOptions {
19+
sourceCompatibility = '1.8'
20+
targetCompatibility = '1.8'
21+
}
1822
}
1923

2024
dependencies {
2125
implementation fileTree(dir: 'libs', include: ['*.jar'])
22-
implementation 'com.android.support:leanback-v17:23.4.0'
2326
implementation 'com.github.scribejava:scribejava-apis:5.5.0'
27+
implementation 'com.google.firebase:firebase-database:16.0.5'
2428
}
29+
30+
apply plugin: 'com.google.gms.google-services'

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
package="net.maxbraun.mirror"
55
xmlns:android="http://schemas.android.com/apk/res/android">
66

7-
<uses-feature
8-
android:name="android.software.leanback"
9-
android:required="true"/>
107
<uses-feature
118
android:name="android.hardware.touchscreen"
129
android:required="false"/>
@@ -34,7 +31,6 @@
3431
<intent-filter android:priority="11">
3532
<action android:name="android.intent.action.MAIN"/>
3633
<category android:name="android.intent.category.LAUNCHER"/>
37-
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
3834
<category android:name="android.intent.category.HOME"/>
3935
<category android:name="android.intent.category.DEFAULT"/>
4036
</intent-filter>
@@ -52,7 +48,6 @@
5248
<intent-filter android:priority="11">
5349
<action android:name="android.intent.action.MAIN"/>
5450
<category android:name="android.intent.category.LAUNCHER"/>
55-
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
5651
<category android:name="android.intent.category.HOME"/>
5752
<category android:name="android.intent.category.DEFAULT"/>
5853
</intent-filter>

app/src/main/java/net/maxbraun/mirror/Body.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package net.maxbraun.mirror;
22

33
import android.app.Activity;
4-
import android.content.Context;
54
import android.util.Log;
65

76
import java.util.ArrayList;
87
import java.util.Calendar;
98
import java.util.Collections;
10-
import java.util.Comparator;
119
import java.util.List;
1210
import java.util.Locale;
1311
import java.util.concurrent.TimeUnit;
@@ -146,12 +144,8 @@ private static BodyMeasure[] parseBodyMeasures(JSONObject response) throws JSONE
146144
}
147145

148146
// Make sure the measures are sorted by ascending timestamp.
149-
Collections.sort(bodyMeasures, new Comparator<BodyMeasure>() {
150-
@Override
151-
public int compare(BodyMeasure lhs, BodyMeasure rhs) {
152-
return Long.compare(lhs.timestamp, rhs.timestamp);
153-
}
154-
});
147+
Collections.sort(bodyMeasures,
148+
(BodyMeasure lhs, BodyMeasure rhs) -> Long.compare(lhs.timestamp, rhs.timestamp));
155149

156150
return bodyMeasures.toArray(new BodyMeasure[bodyMeasures.size()]);
157151
}

0 commit comments

Comments
 (0)