diff --git a/.gitignore b/.gitignore index facf74e..a40eeb0 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ cache /external /third_party +/third_party_android node_modules .temp diff --git a/android.mk b/android.mk new file mode 100644 index 0000000..07b6e23 --- /dev/null +++ b/android.mk @@ -0,0 +1,137 @@ +# -------------------- VALUES TO CONFIGURE -------------------- + +include versions.mk + +ifeq ($(V),) +HIDE=@ +MAKE += --no-print-directory +endif +PWD := $(shell pwd) + +# Path to Android NDK +# NDK version must match ndkVersion in app/build.gradle +NDK_PATH := /home/sreimers/Android/Sdk/ndk/$(shell grep ndkVersion app/android/app/build.gradle.kts | sed 's/[^0-9.]*//g') + +# Android API level +API_LEVEL := 26 + + +# Set default from following values: [armeabi-v7a, arm64-v8a, x86_64] +ANDROID_TARGET_ARCH := arm64-v8a + +# -------------------- GENERATED VALUES -------------------- + +ifeq ($(ANDROID_TARGET_ARCH), armeabi-v7a) + TARGET := arm-linux-androideabi + CLANG_TARGET := armv7a-linux-androideabi + ARCH := arm + OPENSSL_ARCH := android-arm + MARCH := armv7-a +else +ifeq ($(ANDROID_TARGET_ARCH), arm64-v8a) + TARGET := aarch64-linux-android + CLANG_TARGET := $(TARGET) + ARCH := arm + OPENSSL_ARCH := android-arm64 + MARCH := armv8-a +else +ifeq ($(ANDROID_TARGET_ARCH), x86_64) + TARGET := x86_64-linux-android + CLANG_TARGET := $(TARGET) + ARCH := x86 + OPENSSL_ARCH := android-x86_64 + MARCH := x86-64 +else + exit 1 +endif +endif +endif + +PLATFORM := android-$(API_LEVEL) + +OS := $(shell uname -s | tr "[A-Z]" "[a-z]") +ifeq ($(OS),linux) + HOST_OS := linux-x86_64 +endif +ifeq ($(OS),darwin) + HOST_OS := darwin-x86_64 +endif + +# Toolchain and sysroot +TOOLCHAIN := $(NDK_PATH)/toolchains/llvm/prebuilt/$(HOST_OS) +CMAKE_TOOLCHAIN_FILE := $(NDK_PATH)/build/cmake/android.toolchain.cmake +SYSROOT := $(TOOLCHAIN)/sysroot +PKG_CONFIG_LIBDIR := $(NDK_PATH)/prebuilt/$(HOST_OS)/lib/pkgconfig + +# Toolchain tools +PATH := $(TOOLCHAIN)/bin:${PATH} +AR := llvm-ar +AS := $(CLANG_TARGET)$(API_LEVEL)-clang +CC := $(CLANG_TARGET)$(API_LEVEL)-clang +CXX := $(CLANG_TARGET)$(API_LEVEL)-clang++ +LD := ld.lld +RANLIB := llvm-ranlib +STRIP := llvm-strip + +CMAKE_ANDROID_FLAGS := \ + -DANDROID=ON \ + -DANDROID_PLATFORM=$(API_LEVEL) \ + -DCMAKE_SYSTEM_NAME=Android \ + -DCMAKE_SYSTEM_VERSION=$(API_LEVEL) \ + -DCMAKE_TOOLCHAIN_FILE=$(CMAKE_TOOLCHAIN_FILE) \ + -DANDROID_ABI=$(ANDROID_TARGET_ARCH) \ + -DCMAKE_ANDROID_ARCH_ABI=$(ANDROID_TARGET_ARCH) \ + -DCMAKE_SKIP_INSTALL_RPATH=ON \ + -DCMAKE_C_COMPILER=$(CC) \ + -DCMAKE_CXX_COMPILER=$(CXX) \ + -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ + -DCMAKE_BUILD_TYPE=Release + +THIRD_PARTY_ROOT := ${PWD}/third_party_android/${ANDROID_TARGET_ARCH} + +default: all + +.PHONY: third_party_dir +third_party_dir: + mkdir -p ${THIRD_PARTY_ROOT}/include + mkdir -p ${THIRD_PARTY_ROOT}/lib + +.PHONY: openssl +openssl: third_party_dir + $(HIDE)cd third_party_android && \ + wget ${OPENSSL_MIRROR}/openssl-${OPENSSL_VERSION}.tar.gz && \ + tar -xzf openssl-${OPENSSL_VERSION}.tar.gz && \ + cp -a openssl-${OPENSSL_VERSION} openssl + @rm -f third_party/openssl-${OPENSSL_VERSION}.tar.gz + $(HIDE)cd third_party_android/openssl && \ + ANDROID_NDK_ROOT=$(NDK_PATH) \ + ./Configure $(OPENSSL_ARCH) no-shared no-tests \ + -U__ANDROID_API__ -D__ANDROID_API__=$(API_LEVEL) && \ + make -j build_libs && \ + cp *.a ${THIRD_PARTY_ROOT}/lib && \ + cp -a include/openssl ${THIRD_PARTY_ROOT}/include/ + +.PHONY: lmdb +lmdb: third_party_dir + $(HIDE)cd third_party_android && \ + git clone https://github.com/LMDB/lmdb && \ + cd lmdb/libraries/liblmdb && \ + make CC=$(CC) -j && \ + cp liblmdb.a ${THIRD_PARTY_ROOT}/lib/ && \ + cp lmdb.h ${THIRD_PARTY_ROOT}/include/ + +.PHONY: opus +opus: third_party_dir + $(HIDE)cd third_party_android && \ + wget ${OPUS_MIRROR}/opus-${OPUS_VERSION}.tar.gz && \ + tar -xzf opus-${OPUS_VERSION}.tar.gz && \ + mv opus-${OPUS_VERSION} opus + $(HIDE)cd third_party_android/opus && \ + CC=$(CC) ./configure --host=${TARGET} --disable-shared --with-pic --enable-dred \ + --enable-deep-plc --enable-osce && \ + make -j && \ + cp .libs/libopus.a ${THIRD_PARTY_ROOT}/lib/ && \ + mkdir -p ${THIRD_PARTY_ROOT}/include/opus && \ + cp include/*.h ${THIRD_PARTY_ROOT}/include/opus/ + +all: openssl lmdb opus diff --git a/app/android/.gitignore b/app/android/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/app/android/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/app/android/.idea/.gitignore b/app/android/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/app/android/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/app/android/.idea/.name b/app/android/.idea/.name new file mode 100644 index 0000000..cd0b553 --- /dev/null +++ b/app/android/.idea/.name @@ -0,0 +1 @@ +Studio Link \ No newline at end of file diff --git a/app/android/.idea/compiler.xml b/app/android/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/app/android/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/android/.idea/deploymentTargetSelector.xml b/app/android/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/app/android/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/android/.idea/gradle.xml b/app/android/.idea/gradle.xml new file mode 100644 index 0000000..0897082 --- /dev/null +++ b/app/android/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/android/.idea/inspectionProfiles/Project_Default.xml b/app/android/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..44ca2d9 --- /dev/null +++ b/app/android/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,41 @@ + + + + \ No newline at end of file diff --git a/app/android/.idea/kotlinc.xml b/app/android/.idea/kotlinc.xml new file mode 100644 index 0000000..fdf8d99 --- /dev/null +++ b/app/android/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/android/.idea/migrations.xml b/app/android/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/app/android/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/android/.idea/misc.xml b/app/android/.idea/misc.xml new file mode 100644 index 0000000..0ad17cb --- /dev/null +++ b/app/android/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/android/.idea/other.xml b/app/android/.idea/other.xml new file mode 100644 index 0000000..0d3a1fb --- /dev/null +++ b/app/android/.idea/other.xml @@ -0,0 +1,263 @@ + + + + + + \ No newline at end of file diff --git a/app/android/.idea/vcs.xml b/app/android/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/app/android/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/android/app/.gitignore b/app/android/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/android/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/android/app/build.gradle.kts b/app/android/app/build.gradle.kts new file mode 100644 index 0000000..472197a --- /dev/null +++ b/app/android/app/build.gradle.kts @@ -0,0 +1,78 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) +} + +android { + namespace = "link.studio.app" + compileSdk = 34 + ndkVersion = "27.0.11902837" + + defaultConfig { + applicationId = "link.studio.app" + minSdk = 26 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + externalNativeBuild { + cmake { + cppFlags += "" + } + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + externalNativeBuild { + cmake { + path = file("src/main/cpp/CMakeLists.txt") + version = "3.22.1" + } + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.webkit) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} \ No newline at end of file diff --git a/app/android/app/proguard-rules.pro b/app/android/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/android/app/proguard-rules.pro @@ -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 \ No newline at end of file diff --git a/app/android/app/src/androidTest/java/link/studio/app/ExampleInstrumentedTest.kt b/app/android/app/src/androidTest/java/link/studio/app/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..4fd953d --- /dev/null +++ b/app/android/app/src/androidTest/java/link/studio/app/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package link.studio.app + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("link.studio.app", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/android/app/src/main/AndroidManifest.xml b/app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6c81dca --- /dev/null +++ b/app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/android/app/src/main/cpp/CMakeLists.txt b/app/android/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..e1ccf55 --- /dev/null +++ b/app/android/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,38 @@ + +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html. +# For more examples on how to use CMake, see https://github.com/android/ndk-samples. + +# Sets the minimum CMake version required for this project. +cmake_minimum_required(VERSION 3.22.1) + +# Declares the project name. The project name can be accessed via ${ PROJECT_NAME}, +# Since this is the top level CMakeLists.txt, the project name is also accessible +# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level +# build script scope). +project("api") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. +# +# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define +# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME} +# is preferred for the same purpose. +# +# In order to load a library into your app from Java/Kotlin, you must call +# System.loadLibrary() and pass the name of the library defined here; +# for GameActivity/NativeActivity derived applications, the same library name must be +# used in the AndroidManifest.xml file. +add_library(${CMAKE_PROJECT_NAME} SHARED + # List C/C++ source files with relative paths to this CMakeLists.txt. + api.c) + +# Specifies libraries CMake should link to your target library. You +# can link libraries from various origins, such as libraries defined in this +# build script, prebuilt third-party libraries, or Android system libraries. +target_link_libraries(${CMAKE_PROJECT_NAME} + # List libraries link to the target library + android + log) diff --git a/app/android/app/src/main/cpp/api.c b/app/android/app/src/main/cpp/api.c new file mode 100644 index 0000000..3569aa0 --- /dev/null +++ b/app/android/app/src/main/cpp/api.c @@ -0,0 +1,5 @@ +#include +#include + + + diff --git a/app/android/app/src/main/java/link/studio/app/MainActivity.kt b/app/android/app/src/main/java/link/studio/app/MainActivity.kt new file mode 100644 index 0000000..c3f7488 --- /dev/null +++ b/app/android/app/src/main/java/link/studio/app/MainActivity.kt @@ -0,0 +1,58 @@ +package link.studio.app + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.webkit.WebResourceError +import android.webkit.WebResourceRequest +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.activity.ComponentActivity +import androidx.activity.enableEdgeToEdge + +private var refused_fail = 0 + +private class MyWebViewClient : WebViewClient() { + override fun onReceivedError( + view: WebView?, + request: WebResourceRequest?, + error: WebResourceError? + ) { + if (error?.errorCode == WebViewClient.ERROR_CONNECT && refused_fail++ < 10) { + Thread.sleep(100) + view?.reload() + } + println("WebView:onReceivedError: " + error?.description) + super.onReceivedError(view, request, error) + } + + override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { + val url = request?.url.toString() + if (Uri.parse(url).host == "localhost") { + // This is your website, so don't override. Let your WebView load + // the page. + return false + } + + Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { + view?.context?.startActivity(this) + } + return true + } +} + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + val myWebView = WebView(this) + setContentView(myWebView) + myWebView.settings.javaScriptEnabled = true + myWebView.loadUrl("http://localhost:9999/") + myWebView.webViewClient = MyWebViewClient() + } + + init { + System.loadLibrary("api") + } +} \ No newline at end of file diff --git a/app/android/app/src/main/res/drawable/ic_launcher_background.xml b/app/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/android/app/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/android/app/src/main/res/values/colors.xml b/app/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/android/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/android/app/src/main/res/values/strings.xml b/app/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..78c4edf --- /dev/null +++ b/app/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Studio Link + \ 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 new file mode 100644 index 0000000..087831a --- /dev/null +++ b/app/android/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +