Skip to content

Commit adfdca0

Browse files
authored
Wear version of Jetcaster (#1290)
Simple wear app with 2 screens for Player and Home based on Horologist media toolkit.
2 parents c3a5252 + acfc5b0 commit adfdca0

36 files changed

+1162
-1
lines changed

Jetcaster/gradle/libs.versions.toml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ secrets = "2.0.1"
5555
# @keep
5656
targetSdk = "33"
5757
version-catalog-update = "0.8.4"
58+
playServicesWearable = "18.1.0"
59+
composeMaterial = "1.2.1"
60+
composeFoundation = "1.2.1"
61+
coreSplashscreen = "1.0.1"
62+
horologistComposeTools = "0.4.8"
63+
horologist = "0.5.25"
64+
roborazzi = "1.11.0"
65+
androidx-wear-compose = "1.3.0"
66+
wear-compose-ui-tooling = "1.3.0"
67+
ui-test-manifest = "1.6.3"
68+
ui-test-junit4 = "1.6.3"
5869

5970
[libraries]
6071
accompanist-adaptive = { module = "com.google.accompanist:accompanist-adaptive", version.ref = "accompanist" }
@@ -126,6 +137,7 @@ googlemaps-maps = { module = "com.google.android.gms:play-services-maps", versio
126137
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
127138
hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" }
128139
hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
140+
dagger-hiltandroidplugin = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "hilt" }
129141
hilt-ext-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hiltExt" }
130142
junit = { module = "junit:junit", version.ref = "junit" }
131143
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
@@ -137,6 +149,33 @@ okhttp3 = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
137149
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
138150
rometools-modules = { module = "com.rometools:rome-modules", version.ref = "rome" }
139151
rometools-rome = { module = "com.rometools:rome", version.ref = "rome" }
152+
play-services-wearable = { group = "com.google.android.gms", name = "play-services-wearable", version.ref = "playServicesWearable" }
153+
compose-material = { group = "androidx.wear.compose", name = "compose-material", version.ref = "composeMaterial" }
154+
compose-foundation = { group = "androidx.wear.compose", name = "compose-foundation", version.ref = "composeFoundation" }
155+
androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "coreSplashscreen" }
156+
horologist-compose-tools = { group = "com.google.android.horologist", name = "horologist-compose-tools", version.ref = "horologistComposeTools" }
157+
horologist-composables = { module = "com.google.android.horologist:horologist-composables", version.ref = "horologist" }
158+
horologist-compose-layout = { module = "com.google.android.horologist:horologist-compose-layout", version.ref = "horologist" }
159+
horologist-compose-material = { module = "com.google.android.horologist:horologist-compose-material", version.ref = "horologist" }
160+
horologist-media-ui = { module = "com.google.android.horologist:horologist-media-ui", version.ref = "horologist" }
161+
horologist-audio-ui = { module = "com.google.android.horologist:horologist-audio-ui", version.ref = "horologist" }
162+
horologist-media-data = { module = "com.google.android.horologist:horologist-media-data", version.ref = "horologist" }
163+
horologist-roboscreenshots = { module = "com.google.android.horologist:horologist-roboscreenshots", version.ref = "horologist" }
164+
roborazzi = { group = "io.github.takahirom.roborazzi", name = "roborazzi", version.ref = "roborazzi" }
165+
roborazzi-compose = { group = "io.github.takahirom.roborazzi", name = "roborazzi-compose", version.ref = "roborazzi" }
166+
roborazzi-rule = { group = "io.github.takahirom.roborazzi", name = "roborazzi-junit-rule", version.ref = "roborazzi" }
167+
androidx-splashscreen = "androidx.core:core-splashscreen:1.0.1"
168+
wear-compose-foundation = { module = "androidx.wear.compose:compose-foundation", version.ref = "androidx-wear-compose" }
169+
wear-compose-material = { module = "androidx.wear.compose:compose-material", version.ref = "androidx-wear-compose" }
170+
wear-compose-navigation = { module = "androidx.wear.compose:compose-navigation", version.ref = "androidx-wear-compose" }
171+
androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core" }
172+
androidx-wear-compose-ui-tooling = { module = "androidx.wear.compose:compose-ui-tooling", version.ref = "wear-compose-ui-tooling" }
173+
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
174+
androidx-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "ui-test-manifest" }
175+
androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "ui-test-junit4" }
176+
test-ext-junit = "androidx.test.ext:junit:1.1.5"
177+
test-espresso-core = "androidx.test.espresso:espresso-core:3.5.1"
178+
compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
140179

141180
[plugins]
142181
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
@@ -150,3 +189,4 @@ kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref =
150189
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
151190
secrets = { id = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin", version.ref = "secrets" }
152191
version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog-update" }
192+
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }

Jetcaster/settings.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ dependencyResolutionManagement {
3535
}
3636
}
3737
rootProject.name = "Jetcaster"
38-
include(":app", ":core", ":designsystem", ":tv-app")
38+
include(":app", ":core", ":designsystem", ":tv-app", ":wear")
39+
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

Jetcaster/wear/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

Jetcaster/wear/build.gradle

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Copyright 2021 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
plugins {
17+
id 'com.android.application'
18+
id 'org.jetbrains.kotlin.android'
19+
alias libs.plugins.roborazzi
20+
alias(libs.plugins.ksp)
21+
}
22+
23+
android {
24+
compileSdk 34
25+
26+
namespace "com.example.jetcaster"
27+
28+
defaultConfig {
29+
applicationId "com.example.jetcaster"
30+
minSdk 26
31+
targetSdk 33
32+
versionCode 1
33+
versionName "1.0"
34+
}
35+
36+
buildTypes {
37+
release {
38+
minifyEnabled true
39+
shrinkResources true
40+
signingConfig signingConfigs.debug
41+
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
42+
}
43+
}
44+
45+
compileOptions {
46+
sourceCompatibility JavaVersion.VERSION_17
47+
targetCompatibility JavaVersion.VERSION_17
48+
coreLibraryDesugaringEnabled true
49+
}
50+
testOptions {
51+
unitTests {
52+
includeAndroidResources true
53+
}
54+
}
55+
kotlinOptions {
56+
jvmTarget = JavaVersion.VERSION_17.majorVersion
57+
}
58+
buildFeatures {
59+
compose true
60+
}
61+
composeOptions {
62+
kotlinCompilerExtensionVersion libs.versions.compose.compiler.get()
63+
}
64+
packagingOptions {
65+
resources {
66+
excludes += "/META-INF/{AL2.0,LGPL2.1}"
67+
excludes += "rome-utils-1.18.0.jar"
68+
}
69+
}
70+
}
71+
72+
dependencies {
73+
74+
75+
def composeBom = platform(libs.androidx.compose.bom)
76+
77+
// General compose dependencies
78+
implementation composeBom
79+
implementation libs.androidx.activity.compose
80+
implementation libs.androidx.splashscreen
81+
82+
// Compose for Wear OS Dependencies
83+
// NOTE: DO NOT INCLUDE a dependency on androidx.compose.material:material.
84+
// androidx.wear.compose:compose-material is designed as a replacement not an addition to
85+
// androidx.compose.material:material. If there are features from that you feel are missing from
86+
// androidx.wear.compose:compose-material please raise a bug to let us know:
87+
// https://issuetracker.google.com/issues/new?component=1077552&template=1598429&pli=1
88+
implementation libs.wear.compose.material
89+
90+
// Foundation is additive, so you can use the mobile version in your Wear OS app.
91+
implementation libs.wear.compose.foundation
92+
implementation(libs.androidx.material.icons.core)
93+
implementation(libs.androidx.compose.material.iconsExtended)
94+
95+
// Horologist for correct Compose layout
96+
implementation libs.horologist.composables
97+
implementation libs.horologist.compose.layout
98+
implementation libs.horologist.compose.material
99+
100+
//Horologist Media toolkit
101+
implementation libs.horologist.media.ui
102+
implementation libs.horologist.audio.ui
103+
implementation libs.horologist.media.data
104+
105+
// Preview Tooling
106+
implementation libs.compose.ui.tooling.preview
107+
implementation(libs.androidx.compose.ui.tooling)
108+
implementation libs.androidx.wear.compose.ui.tooling
109+
110+
// If you are using Compose Navigation, use the Wear OS version (NOT the
111+
// androidx.navigation:navigation-compose version), that is, uncomment the line below.
112+
implementation libs.wear.compose.navigation
113+
114+
implementation libs.androidx.ui.test.manifest
115+
116+
implementation(libs.coil.kt.compose)
117+
118+
coreLibraryDesugaring(libs.core.jdk.desugaring)
119+
120+
implementation projects.core
121+
implementation projects.designsystem
122+
123+
124+
// Testing
125+
testImplementation libs.androidx.ui.test.junit4
126+
testImplementation libs.junit
127+
testImplementation libs.robolectric
128+
testImplementation libs.roborazzi
129+
testImplementation libs.roborazzi.compose
130+
testImplementation libs.roborazzi.rule
131+
testImplementation(libs.horologist.roboscreenshots) {
132+
exclude(group: "com.github.QuickBirdEng.kotlin-snapshot-testing")
133+
}
134+
135+
androidTestImplementation libs.test.ext.junit
136+
androidTestImplementation libs.test.espresso.core
137+
androidTestImplementation libs.compose.ui.test.junit4
138+
androidTestImplementation composeBom
139+
140+
debugImplementation(libs.androidx.compose.ui.tooling)
141+
debugImplementation libs.androidx.ui.test.manifest
142+
debugImplementation composeBom
143+
}

Jetcaster/wear/proguard-rules.pro

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright (C) 2021 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# Add project specific ProGuard rules here.
16+
# You can control the set of applied configuration files using the
17+
# proguardFiles setting in build.gradle.
18+
#
19+
# For more details, see
20+
# http://developer.android.com/guide/developing/tools/proguard.html
21+
22+
# If your project uses WebView with JS, uncomment the following
23+
# and specify the fully qualified class name to the JavaScript interface
24+
# class:
25+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
26+
# public *;
27+
#}
28+
29+
# Uncomment this to preserve the line number information for
30+
# debugging stack traces.
31+
#-keepattributes SourceFile,LineNumberTable
32+
33+
# If you keep the line number information, uncomment this to
34+
# hide the original source file name.
35+
#-renamesourcefileattribute SourceFile
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright (C) 2021 The Android Open Source Project
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
-->
14+
<manifest
15+
xmlns:android="http://schemas.android.com/apk/res/android">
16+
17+
<uses-permission android:name="android.permission.WAKE_LOCK" />
18+
19+
<uses-feature android:name="android.hardware.type.watch" />
20+
21+
<application
22+
android:name=".JetcasterWearApplication"
23+
android:allowBackup="true"
24+
android:icon="@mipmap/ic_launcher"
25+
android:label="@string/app_name"
26+
android:supportsRtl="true"
27+
android:theme="@android:style/Theme.DeviceDefault">
28+
<uses-library
29+
android:name="com.google.android.wearable"
30+
android:required="true" />
31+
<!--
32+
Set to true if your app is Standalone, that is, it does not require the handheld
33+
app to run.
34+
-->
35+
<meta-data
36+
android:name="com.google.android.wearable.standalone"
37+
android:value="true" />
38+
39+
<activity
40+
android:name=".MainActivity"
41+
android:exported="true"
42+
android:label="@string/app_name"
43+
android:theme="@style/Theme.App.Starting">
44+
<intent-filter>
45+
<action android:name="android.intent.action.MAIN" />
46+
47+
<category android:name="android.intent.category.LAUNCHER" />
48+
</intent-filter>
49+
</activity>
50+
</application>
51+
52+
</manifest>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.jetcaster
18+
19+
import android.app.Application
20+
import android.os.StrictMode
21+
import coil.ImageLoader
22+
import coil.ImageLoaderFactory
23+
import com.example.jetcaster.core.data.di.Graph
24+
25+
class JetcasterWearApplication : Application(), ImageLoaderFactory {
26+
27+
override fun onCreate() {
28+
super.onCreate()
29+
Graph.provide(this)
30+
setStrictMode()
31+
}
32+
33+
private fun setStrictMode() {
34+
StrictMode.setThreadPolicy(
35+
StrictMode.ThreadPolicy.Builder()
36+
.detectDiskReads()
37+
.detectDiskWrites()
38+
.detectNetwork()
39+
.penaltyLog()
40+
.build(),
41+
)
42+
}
43+
44+
override fun newImageLoader(): ImageLoader {
45+
return ImageLoader.Builder(this)
46+
// Disable `Cache-Control` header support as some podcast images disable disk caching.
47+
.respectCacheHeaders(false)
48+
.build()
49+
}
50+
}

0 commit comments

Comments
 (0)