Skip to content

Commit

Permalink
start add wear os, do login
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiebe committed Feb 8, 2024
1 parent d20ecaf commit 84c29a1
Show file tree
Hide file tree
Showing 26 changed files with 484 additions and 2 deletions.
1 change: 1 addition & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,5 @@ dependencies {
implementation(libs.compose.material)

implementation(libs.decompose.core)
implementation(libs.play.services.wearable)
}
14 changes: 14 additions & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
</intent-filter>
</activity>

<activity
android:name="nl.tiebe.otarium.androidApp.WearLoginActivity"
android:exported="true"
android:theme="@style/Theme.AppCompat.NoActionBar" >
</activity>

<meta-data
android:name="google_analytics_adid_collection_enabled"
android:value="false" />
Expand All @@ -53,6 +59,14 @@
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>

<service android:name=".WearListener"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<data android:scheme="wear" android:host="*" android:pathPrefix="/wear_login" />
</intent-filter>
</service>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package nl.tiebe.otarium.androidApp

import android.content.Intent
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.WearableListenerService

class WearListener : WearableListenerService() {
override fun onMessageReceived(messageEvent: MessageEvent) {
val intent = Intent(applicationContext, WearLoginActivity::class.java)
intent.putExtra("uri", messageEvent.data)
intent.putExtra("node", messageEvent.sourceNodeId)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

startActivity(intent)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package nl.tiebe.otarium.androidApp

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.ViewGroup
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.addCallback
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import com.google.android.gms.wearable.Wearable
import nl.tiebe.otarium.ui.login.getActivity
import nl.tiebe.otarium.utils.ui.Android

class WearLoginActivity : AppCompatActivity() {
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val onBackDispatcher = onBackPressedDispatcher

Android.context = this
Android.window = window

val url = intent.extras?.getByteArray("uri")!!.decodeToString()
val node = intent.extras?.getString("node")!!

setContent {
AndroidView(factory = {
val webViewClient: WebViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView,
webResourceRequest: WebResourceRequest
): Boolean {
val checkUrl = webResourceRequest.url.toString()

if (checkUrl.startsWith("m6loapp://oauth2redirect")) {
println("sending....")
Wearable.getMessageClient(applicationContext).sendMessage(node, "/login_completed", checkUrl.toByteArray())
return true
}

return false
}

override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
if (request?.url.toString().contains("playconsolelogin")) {
Wearable.getMessageClient(applicationContext).sendMessage(node, "/login_bypass", null)
}
return super.shouldInterceptRequest(view, request)
}
}

val webView = WebView(it).apply {
settings.javaScriptEnabled = true
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
this.webViewClient = webViewClient
loadUrl(url)
}

onBackDispatcher.addCallback {
if (webView.canGoBack()) webView.goBack()
else getActivity(it)?.finishAfterTransition()
}

webView
}, update = {
it.loadUrl(url)
}, modifier = Modifier.fillMaxSize())
}

}

}
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
alias(libs.plugins.complete.kotlin)
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.kotlinAndroid) apply false
}

buildscript {
Expand Down
26 changes: 25 additions & 1 deletion libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,19 @@ colormath = "3.4.0"

kotlin-datetime = "0.5.0"

# --- IDEA ---
# Make navigation between agenda and grades screen like spotify. That means first page is agenda, second page is grades. You can only swipe to exit on the agenda page.

skiko = "0.7.85.4"
agp = "8.2.2"
kotlin190 = "1.9.0"
play-services-wearable = "18.1.0"
wear-compose-bom = "2024.02.00"
compose-material = "1.3.0"
compose-material3 = "1.0.0-alpha17"
compose-foundation = "1.3.0"
core-splashscreen = "1.0.1"
wear-phone-interactions = "1.0.1"

[libraries]
compose-activity = { group = "androidx.activity", name = "activity-compose", version.ref = "compose-activity" }
Expand Down Expand Up @@ -82,9 +94,21 @@ guava-coroutines = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines
androidx-work = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work-android" }

skiko = { group = "org.jetbrains.skiko", name = "skiko", version.ref = "skiko" }
play-services-wearable = { group = "com.google.android.gms", name = "play-services-wearable", version.ref = "play-services-wearable" }
wear-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "wear-compose-bom" }
wear-tooling-preview = { group = "androidx.wear", name = "wear-tooling-preview" }
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-wear-compose-compose-material = { group = "androidx.wear.compose", name = "compose-material", version.ref = "compose-material" }
androidx-wear-compose-compose-material3 = { group = "androidx.wear.compose", name = "compose-material3", version.ref = "compose-material3" }
compose-foundation = { group = "androidx.wear.compose", name = "compose-foundation", version.ref = "compose-foundation" }
core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "core-splashscreen" }
androidx-wear-phone-interactions = { group = "androidx.wear", name = "wear-phone-interactions", version.ref = "wear-phone-interactions" }

[plugins]
mokoresources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko" }
complete_kotlin = { id = "com.louiscad.complete-kotlin", version.ref = "complete-kotlin" }
compose = { id = "org.jetbrains.compose", version.ref = "compose" }
buildkonfig = { id = "com.codingfeline.buildkonfig", version.ref = "buildkonfig" }
buildkonfig = { id = "com.codingfeline.buildkonfig", version.ref = "buildkonfig" }
androidApplication = { id = "com.android.application", version.ref = "agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin190" }
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ rootProject.name = "Otarium"

include(":androidApp")
include(":shared")
include(":wearApp")
2 changes: 1 addition & 1 deletion shared/src/commonMain/kotlin/nl/tiebe/otarium/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ internal val LocalComponentContext: ProvidableCompositionLocal<ComponentContext>
staticCompositionLocalOf { error("Root component context was not provided") }

@Composable
internal fun ProvideComponentContext(componentContext: ComponentContext, content: @Composable () -> Unit) {
fun ProvideComponentContext(componentContext: ComponentContext, content: @Composable () -> Unit) {
CompositionLocalProvider(LocalComponentContext provides componentContext, content = content)
}
1 change: 1 addition & 0 deletions wearApp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
69 changes: 69 additions & 0 deletions wearApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
plugins {
id("com.android.application")
kotlin("android")
id("kotlin-parcelize")
id("kotlinx-serialization")
}

android {
namespace = "nl.tiebe.otarium.wear"
compileSdk = 34

defaultConfig {
applicationId = "nl.tiebe.otarium"
minSdk = 30
targetSdk = libs.versions.android.sdk.compile.get().toInt()
versionCode = libs.versions.app.version.code.get().toInt()
versionName = libs.versions.app.version.string.get()
vectorDrawables {
useSupportLibrary = true
}

}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}
}

dependencies {
implementation(project(":shared"))

implementation(libs.play.services.wearable)
implementation(platform(libs.wear.compose.bom))
implementation(libs.compose.ui)
// implementation(libs.wear.tooling.preview)
implementation(libs.androidx.wear.compose.compose.material)
implementation(libs.androidx.wear.compose.compose.material3)
implementation(libs.compose.foundation)
implementation(libs.compose.activity)
implementation(libs.core.splashscreen)
implementation(libs.androidx.wear.phone.interactions)
debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)

implementation(libs.decompose.core)
implementation(libs.decompose.compose)

api(libs.moko.resources.core)
implementation(libs.magister.api)
}
21 changes: 21 additions & 0 deletions wearApp/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
35 changes: 35 additions & 0 deletions wearApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-feature android:name="android.hardware.type.watch" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault">
<uses-library
android:name="com.google.android.wearable"
android:required="true" />

<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />

<activity
android:name=".MainActivity"
android:exported="true"
android:taskAffinity=""
android:theme="@style/MainActivityTheme.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
52 changes: 52 additions & 0 deletions wearApp/src/main/java/nl/tiebe/otarium/wear/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package nl.tiebe.otarium.wear

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.defaultComponentContext
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import com.google.android.gms.wearable.MessageEvent
import nl.tiebe.otarium.ProvideComponentContext
import nl.tiebe.otarium.logic.default.DefaultRootComponent
import nl.tiebe.otarium.logic.root.RootComponent
import nl.tiebe.otarium.setup
import nl.tiebe.otarium.wear.theme.OtariumTheme
import nl.tiebe.otarium.wear.ui.home.HomeScreen
import nl.tiebe.otarium.wear.ui.login.LoginScreen

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()

super.onCreate(savedInstanceState)

setTheme(android.R.style.Theme_DeviceDefault)

val componentContext = defaultComponentContext()

setContent {
ProvideComponentContext(componentContext) {
setup()

WearApp(DefaultRootComponent(componentContext), componentContext)
}
}
}
}

@Composable
fun WearApp(component: RootComponent, componentContext: ComponentContext) {
OtariumTheme {
val currentScreen by component.currentScreen.subscribeAsState()

when (val screen = currentScreen) {
is RootComponent.ChildScreen.HomeChild -> HomeScreen(componentContext)
is RootComponent.ChildScreen.LoginChild -> LoginScreen(screen.component)
is RootComponent.ChildScreen.OnboardingChild -> screen.component.exitOnboarding()
}
}
}
Loading

0 comments on commit 84c29a1

Please sign in to comment.