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/CMakeLists.txt b/CMakeLists.txt index 6b633aa..a7f8a29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,6 @@ project( VERSION 24.1.0 LANGUAGES C) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) # ############################################################################# # diff --git a/Makefile b/Makefile index 764fb7c..af100c8 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ distclean: clean cleaner .PHONY: ccheck ccheck: - test/ccheck.py libsl Makefile test app + test/ccheck.py libsl Makefile test app/linux .PHONY: tree tree: diff --git a/README.md b/README.md index bbce7c5..171660e 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,14 @@ Please use the prebuilt binarys at https://doku.studio-link.de/standalone/instal make ``` +## Prepare Android 3rd Party builds + +```bash +make external +make -f android.mk ANDROID_TARGET_ARCH=arm64-v8a +make -f android.mk ANDROID_TARGET_ARCH=x86_64 # emulator +``` + ## Supported Platforms (planned) - Windows 64Bit diff --git a/android.mk b/android.mk new file mode 100644 index 0000000..48f0d3d --- /dev/null +++ b/android.mk @@ -0,0 +1,145 @@ +# -------------------- 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 := /opt/Android/Sdk/ndk/$(shell grep ndkVersion app/android/app/build.gradle.kts | sed 's/[^0-9.]*//g') + +# Android API level 26 == Android 8.0 +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: cacert +cacert: third_party_android/cacert.pem + +third_party_android/cacert.pem: + wget https://curl.se/ca/cacert.pem -O third_party_android/cacert.pem + +.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 && \ + rm -rf openssl && \ + 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 && \ + rm -rf lmdb && \ + 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 && \ + rm -rf opus && \ + 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 cacert 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..9b6f06c --- /dev/null +++ b/app/android/.idea/deploymentTargetSelector.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ 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..8978d23 --- /dev/null +++ b/app/android/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ 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..4604c44 --- /dev/null +++ b/app/android/.idea/other.xml @@ -0,0 +1,252 @@ + + + + + + \ 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..0c3235e --- /dev/null +++ b/app/android/.idea/vcs.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/android/app/.gitignore b/app/android/app/.gitignore new file mode 100644 index 0000000..67e07b8 --- /dev/null +++ b/app/android/app/.gitignore @@ -0,0 +1,2 @@ +/build +/release diff --git a/app/android/app/build.gradle.kts b/app/android/app/build.gradle.kts new file mode 100644 index 0000000..831de57 --- /dev/null +++ b/app/android/app/build.gradle.kts @@ -0,0 +1,83 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) +} + +android { + namespace = "link.studio.app" + compileSdk = 34 + ndkVersion = "27.0.12077973" + + defaultConfig { + applicationId = "link.studio.app" + minSdk = 26 + targetSdk = 34 + versionCode = 24010 + versionName = "24.1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + externalNativeBuild { + cmake { + arguments += listOf("-DANDROID_STL=c++_shared") + } + } + + ndk { + abiFilters.addAll(arrayOf("arm64-v8a", "x86_64")) + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + signingConfig = signingConfigs.getByName("debug") + } + } + 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) +} 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..9287c68 --- /dev/null +++ b/app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..de51f04 --- /dev/null +++ b/app/android/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,80 @@ + +# 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") + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/external/third_party/${CMAKE_ANDROID_ARCH_ABI} + ${CMAKE_CURRENT_SOURCE_DIR}/external/re + ${CMAKE_CURRENT_SOURCE_DIR}/external/libsl/include +) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +set(RE_LIBRARY + re + CACHE STRING "") + +set(LIBRE_BUILD_SHARED + OFF + CACHE STRING "") + +set(STATIC + ON + CACHE BOOL "") + +set(MODULES + auconv + auresamp + dtls_srtp + g711 + ice + opus + turn + netroam + opensles + CACHE STRING "") + +# Baresip dependencies +add_subdirectory(external/re EXCLUDE_FROM_ALL) +add_subdirectory(external/baresip EXCLUDE_FROM_ALL) + +find_package(re CONFIG REQUIRED) + +add_compile_definitions(SL_VERSION="${PROJECT_VERSION}") +add_subdirectory(external/libsl EXCLUDE_FROM_ALL) + +# 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 sl baresip re) 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..f506c50 --- /dev/null +++ b/app/android/app/src/main/cpp/api.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "logger.h" + +static thrd_t t; + +static void log_handler(uint32_t level, const char *msg) +{ + LOGD("%s", msg); +} + +static struct log lg = { + .h = log_handler, +}; + +static void dbg_print(int level, const char *p, size_t len, void *arg) +{ + LOGD("%s", p); +} + +static int sl_thread(void *arg) +{ + int err; + err = sl_baresip_init(NULL); + LOGD("Startup init: %d", err); + if (err) + return err; + + err = sl_init(); + if (err) + return err; + + err = sl_main(); + + sl_close(); + + LOGD("Exit"); + return err; +} + + +JNIEXPORT jint JNICALL Java_link_studio_app_Api_slStart(JNIEnv *env, jobject obj, jstring jPath) +{ + const char *path = (*env)->GetStringUTFChars(env, jPath, 0); + + dbg_handler_set(dbg_print, NULL); + log_register_handler(&lg); + + sl_conf_path_set(path); + + int ret = thrd_create(&t, sl_thread, NULL); + if (ret != thrd_success) + return ENOMEM; + + return 0; +} \ No newline at end of file diff --git a/app/android/app/src/main/cpp/external/baresip b/app/android/app/src/main/cpp/external/baresip new file mode 120000 index 0000000..785d9f9 --- /dev/null +++ b/app/android/app/src/main/cpp/external/baresip @@ -0,0 +1 @@ +../../../../../../../external/baresip \ No newline at end of file diff --git a/app/android/app/src/main/cpp/external/libsl b/app/android/app/src/main/cpp/external/libsl new file mode 120000 index 0000000..ca10514 --- /dev/null +++ b/app/android/app/src/main/cpp/external/libsl @@ -0,0 +1 @@ +../../../../../../../libsl \ No newline at end of file diff --git a/app/android/app/src/main/cpp/external/re b/app/android/app/src/main/cpp/external/re new file mode 120000 index 0000000..1afb84f --- /dev/null +++ b/app/android/app/src/main/cpp/external/re @@ -0,0 +1 @@ +../../../../../../../external/re \ No newline at end of file diff --git a/app/android/app/src/main/cpp/external/third_party b/app/android/app/src/main/cpp/external/third_party new file mode 120000 index 0000000..fb5ad0a --- /dev/null +++ b/app/android/app/src/main/cpp/external/third_party @@ -0,0 +1 @@ +../../../../../../../third_party_android \ No newline at end of file diff --git a/app/android/app/src/main/cpp/external/webui b/app/android/app/src/main/cpp/external/webui new file mode 120000 index 0000000..ef26221 --- /dev/null +++ b/app/android/app/src/main/cpp/external/webui @@ -0,0 +1 @@ +../../../../../../../webui \ No newline at end of file diff --git a/app/android/app/src/main/cpp/logger.h b/app/android/app/src/main/cpp/logger.h new file mode 100644 index 0000000..555598d --- /dev/null +++ b/app/android/app/src/main/cpp/logger.h @@ -0,0 +1,23 @@ +// +// Created by sreimers on 7/2/24. +// + +#ifndef STUDIO_LINK_LOGGER_H +#define STUDIO_LINK_LOGGER_H +#define LOG_TAG "SL Lib" + +#define LOGD(...) \ + ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) + +#define LOGI(...) \ + if (log_level_get() < LEVEL_WARN) \ + ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) + +#define LOGW(...) \ + if (log_level_get() < LEVEL_ERROR) \ + ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) + +#define LOGE(...) \ + if (log_level_get() <= LEVEL_ERROR) \ + ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif //STUDIO_LINK_LOGGER_H diff --git a/app/android/app/src/main/ic_launcher-playstore.png b/app/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..6092a88 Binary files /dev/null and b/app/android/app/src/main/ic_launcher-playstore.png differ diff --git a/app/android/app/src/main/java/link/studio/app/Api.kt b/app/android/app/src/main/java/link/studio/app/Api.kt new file mode 100644 index 0000000..e0df094 --- /dev/null +++ b/app/android/app/src/main/java/link/studio/app/Api.kt @@ -0,0 +1,5 @@ +package link.studio.app + +object Api { + external fun slStart(path: String): Int +} \ No newline at end of file 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..eb16d93 --- /dev/null +++ b/app/android/app/src/main/java/link/studio/app/MainActivity.kt @@ -0,0 +1,69 @@ +package link.studio.app + +import android.content.Intent +import android.content.pm.PackageManager +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 +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat + +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?) { + if (ContextCompat.checkSelfPermission(this, + android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + val permissions = arrayOf(android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE) + ActivityCompat.requestPermissions(this, permissions,0) + } + + Api.slStart(filesDir.absolutePath) + 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-v26/ic_launcher.xml b/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ 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..f0861f5 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_foreground.webp b/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..57629d4 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.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..f228adb 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..0f8dc22 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_foreground.webp b/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..78265a7 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.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..d7e714a 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..d68a4c0 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_foreground.webp b/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..242d922 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.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..d67e606 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..0cda83b 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_foreground.webp b/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..f08a358 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.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..0ce5da6 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..78f1ff2 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_foreground.webp b/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..66e11c1 Binary files /dev/null and b/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.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..b34d49f 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/ic_launcher_background.xml b/app/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..bf726f3 --- /dev/null +++ b/app/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FD8026 + \ 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 @@ + + + +