From e43424ef7b7f0bbd6f5b82ab3dd135d24f2df06f Mon Sep 17 00:00:00 2001 From: Ruben Horn <> Date: Tue, 6 Dec 2022 16:06:48 +0100 Subject: [PATCH] Android app v1.1 --- Makefile | 12 ++- app/android/app/build.gradle | 6 +- .../java/vu/storm/stoka_tv/MainActivity.kt | 73 +++++++++++++++++-- .../app/src/main/res/values/strings.xml | 1 - .../app/src/main/res/values/themes.xml | 3 + docs/README.md | 12 +-- frontend/index.html | 3 +- frontend/src/config.js | 2 +- 8 files changed, 93 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index d496183..e653671 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,8 @@ error: @echo "Use 'make tizen-app' to build the Tizen application" @echo "Use 'make install-tizen-app TARGET=\"\"' to install the Tizen application" @echo "Use 'make clean-tizen-app' to delete all packaged Tizen applications" + @echo "Use 'make android-app' to build the Android application" + @echo "Use 'make clean-android-app' to delete all packaged Android applications" @echo "Use 'example-media' to generate test images" @exit 1 @@ -41,8 +43,16 @@ install-tizen-app: app/tizen/StoKa-TV.wgt clean-tizen-app: @ls app/tizen | grep "^.*\.wgt" | sed 's/^/app\/tizen\//g' | xargs rm -f +.PHONY: android-app +android-app: + @bash -c "cd app/android/ && bash gradlew assembleDebug" + +.PHONY: clean-android-app +clean-android-app: + @bash -c "cd app/android/ && bash gradlew clean" + .PHONY: clean -clean: clean-tizen-app clean-images +clean: clean-tizen-app clean-android-app clean-images .PHONY: example-media example-media: diff --git a/app/android/app/build.gradle b/app/android/app/build.gradle index 960d4ed..b6d25af 100644 --- a/app/android/app/build.gradle +++ b/app/android/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "vu.storm.stoka_tv" minSdkVersion 21 targetSdkVersion 26 // Android 8.0 - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "1.1" } @@ -31,4 +31,4 @@ dependencies { implementation 'androidx.leanback:leanback:1.0.0' implementation 'androidx.appcompat:appcompat:1.4.0' implementation 'com.github.bumptech.glide:glide:4.11.0' -} \ No newline at end of file +} diff --git a/app/android/app/src/main/java/vu/storm/stoka_tv/MainActivity.kt b/app/android/app/src/main/java/vu/storm/stoka_tv/MainActivity.kt index ba9e329..252d41f 100644 --- a/app/android/app/src/main/java/vu/storm/stoka_tv/MainActivity.kt +++ b/app/android/app/src/main/java/vu/storm/stoka_tv/MainActivity.kt @@ -9,20 +9,80 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.fragment.app.FragmentActivity +import android.content.Context +import android.widget.EditText +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.view.ContextThemeWrapper +import android.view.KeyEvent +import android.webkit.SslErrorHandler +import android.net.http.SslError class MainActivity : FragmentActivity() { + companion object { + const val SHARED_PREFS_NAME = "prefs" + const val KEY_URL = "url" + } + + lateinit var webView: WebView + @SuppressLint("SetJavaScriptEnabled") - private fun initWebview() { - val webView = findViewById(R.id.web_view) + private fun initUI() { webView.settings.javaScriptEnabled = true webView.webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView?, url: String?) { - webView.visibility = View.VISIBLE; + webView.visibility = View.VISIBLE + val expectedTitle = "StoKa-TV" + if (webView.title != expectedTitle) { + webView.loadData( + "$expectedTitle

Blocked!

", + "text/html", + "UTF-8" + ) + } } + + override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) { + // Ignore SSL certificate errors + handler?.proceed() + } + } + val prefs = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE) + if (prefs.getString(KEY_URL, "")!!.trim().isNotEmpty()) { + webView.loadUrl(prefs.getString(KEY_URL, "")!!) + } else { + // Show dialog to enter URL initially + updateAndLoadUrl() + } + } + + fun updateAndLoadUrl() { + val urlEditText = EditText(this) + urlEditText.setHint("example.org") + val prefs = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE) + urlEditText.setText(prefs.getString(KEY_URL, "")) + AlertDialog.Builder(ContextThemeWrapper(this, R.style.Theme_StoKaTV_Dialog)) + .setTitle("Settings") + .setMessage("Enter the URL of the web app") + .setView(urlEditText) + .setPositiveButton("Update", { dialog, _ -> + val url = urlEditText.getText().toString().trim() + webView.loadUrl(url) + prefs.edit().putString(KEY_URL, url).apply() + dialog.dismiss() + }) + .setNegativeButton("Cancel", { dialog, _ -> + dialog.dismiss() + }) + .show() + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + if (keyCode == KeyEvent.KEYCODE_MENU) { + updateAndLoadUrl() + return true } - val url = getString(R.string.web_app_url) - webView.loadUrl(url) + return super.onKeyDown(keyCode, event) } private fun hideSystemUI() { @@ -36,7 +96,8 @@ class MainActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - initWebview() + webView = findViewById(R.id.web_view) + initUI() } override fun onResume() { diff --git a/app/android/app/src/main/res/values/strings.xml b/app/android/app/src/main/res/values/strings.xml index 83c9702..801b193 100644 --- a/app/android/app/src/main/res/values/strings.xml +++ b/app/android/app/src/main/res/values/strings.xml @@ -1,4 +1,3 @@ StoKa-TV - https://stoka-tv.storm.vu/ \ No newline at end of file diff --git a/app/android/app/src/main/res/values/themes.xml b/app/android/app/src/main/res/values/themes.xml index 1f6c3cc..b807a69 100644 --- a/app/android/app/src/main/res/values/themes.xml +++ b/app/android/app/src/main/res/values/themes.xml @@ -4,4 +4,7 @@ true true + \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 8f6a7a3..c920a39 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,7 +22,6 @@ This application is also available in the browser to preview/review the content. ![Use-case Content Management](./use-case_cms.drawio.svg) ## Prerequisites -+ Linux (Do all of us a favor and use a real operating system 🙃) + [Bash](https://www.gnu.org/software/bash/) + [GNU Make](https://www.gnu.org/software/make/) + [Docker Engine](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) (...or [Podman](https://podman.io/) and [Podman Compose](https://github.com/containers/podman-compose)) @@ -46,7 +45,7 @@ The following optimizations should be performed before deploying the web applica ⚠ Review the contents of `.env`! -## Installing the Tizen application +## ~~Installing the Tizen application~~ (deprecated) 1. Set frontend base url in `/app/tizen/config.js` 2. Connect to the same network as the TV 3. Set up the TV for debugging by going to "apps", pressing "1 2 3 4 5" on the remote and enter the IP address of the host computer. @@ -55,9 +54,9 @@ The following optimizations should be performed before deploying the web applica ⚠ When using the TV emulator, you should load and run the project through Tizen Studio instead. ## Android TV -Since Android is a superiour platform compared to Tizen, you may of course choose to target it instead. -Before building the `.apk` file, you should set the frontend base url in `/app/android/app/src/main/res/values/strings.xml`. -You can either sideload the app from the file system or set your device into developer mode and debug it from Android Studio or using the adb cli. +Since Android is a superiour platform compared to Tizen, you may of course choose to target it instead. +You can either sideload the app from the file system or set your device into developer mode and debug it from Android Studio or using the adb cli. +The frontend base url must be configured at the first start of the app. ## Debugging You can debug the API container using the Crome DevTools by going to `chrome://inspect`. @@ -103,4 +102,5 @@ To get started run `make example-media`. (⚠ Requires [ImageMagic](https://imag | Previous arrangement | ▶ | `Arrow Left` | | Toggle borrel menu | 🔼 | `Arrow Up` | | Toggle help pop-up | 🔽 | `Arrow Down` | -| Select arrangment | 0-9 | `0`-`9` | +| Select arrangment | `0`-`9` | `0`-`9` | +| Set base frontend url | `Menu` | n/a | diff --git a/frontend/index.html b/frontend/index.html index e373985..3df7e56 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,7 +1,8 @@ - Loading... + + StoKa-TV diff --git a/frontend/src/config.js b/frontend/src/config.js index a59afef..cabad03 100644 --- a/frontend/src/config.js +++ b/frontend/src/config.js @@ -4,7 +4,7 @@ const baseUrl = window.location.href.split('/').slice(0, -1).join('/'); define(function(require, exports, module) { module.exports = { - title: 'StoKa-TV', + title: 'StoKa-TV', // Do NOT change title apiBaseUrl: baseUrl + '/api', titleTimeout: 3000, notFoundTimeout: 1500,