From 45f2df661b958660c11cc354e6e4631fee54de0d Mon Sep 17 00:00:00 2001
From: Miuzarte <982809597@qq.com>
Date: Thu, 19 Mar 2026 08:53:26 +0800
Subject: [PATCH] first commit
---
.github/workflows/android.yml | 218 ++++
ScrcpyForAndroid.code-workspace | 19 +
app/.gitignore | 1 +
app/build.gradle.kts | 66 +
app/proguard-rules.pro | 21 +
.../ExampleInstrumentedTest.kt | 24 +
app/src/main/AndroidManifest.xml | 29 +
app/src/main/assets/bin/scrcpy-server-v3.3.4 | Bin 0 -> 90980 bytes
.../miuzarte/scrcpyforandroid/MainActivity.kt | 18 +
.../scrcpyforandroid/NativeCoreFacade.kt | 654 ++++++++++
.../scrcpyforandroid/constants/AppDefaults.kt | 74 ++
.../constants/AppPreferenceKeys.kt | 58 +
.../constants/ScrcpyPresets.kt | 7 +
.../constants/UiAndroidKeycodes.kt | 14 +
.../scrcpyforandroid/constants/UiMotion.kt | 6 +
.../scrcpyforandroid/constants/UiSpacing.kt | 23 +
.../scrcpyforandroid/haptics/AppHaptics.kt | 32 +
.../scrcpyforandroid/models/DeviceModels.kt | 14 +
.../nativecore/AnnexBDecoder.kt | 161 +++
.../nativecore/DirectAdbClient.kt | 506 ++++++++
.../nativecore/NativeAdbService.kt | 84 ++
.../nativecore/ScrcpyAudioPlayer.kt | 201 +++
.../nativecore/ScrcpySessionManager.kt | 1060 ++++++++++++++++
.../pages/AdvancedConfigPage.kt | 676 +++++++++++
.../scrcpyforandroid/pages/DevicePage.kt | 1080 +++++++++++++++++
.../pages/FullscreenControlPage.kt | 163 +++
.../scrcpyforandroid/pages/MainPage.kt | 728 +++++++++++
.../scrcpyforandroid/pages/SettingsPage.kt | 207 ++++
.../pages/VirtualButtonOrderPage.kt | 164 +++
.../scrcpyforandroid/scaffolds/PageLayouts.kt | 51 +
.../scrcpyforandroid/scaffolds/SuperSlide.kt | 140 +++
.../services/AppSettingsStore.kt | 214 ++++
.../services/DeviceConnectionLogic.kt | 35 +
.../services/QuickDeviceStore.kt | 110 ++
.../scrcpyforandroid/widgets/DeviceWidgets.kt | 1055 ++++++++++++++++
.../widgets/SectionSmallTitle.kt | 21 +
.../widgets/SortableCardList.kt | 140 +++
.../widgets/StatusCardModels.kt | 166 +++
.../widgets/VirtualButtons.kt | 282 +++++
.../res/drawable/ic_launcher_background.xml | 170 +++
.../res/drawable/ic_launcher_foreground.xml | 30 +
.../main/res/mipmap-anydpi/ic_launcher.xml | 6 +
.../res/mipmap-anydpi/ic_launcher_round.xml | 6 +
app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes
.../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes
app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes
.../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes
.../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes
.../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes
app/src/main/res/values-night/themes.xml | 16 +
app/src/main/res/values/colors.xml | 10 +
app/src/main/res/values/strings.xml | 3 +
app/src/main/res/values/themes.xml | 16 +
app/src/main/res/xml/backup_rules.xml | 13 +
.../main/res/xml/data_extraction_rules.xml | 19 +
.../scrcpyforandroid/ExampleUnitTest.kt | 17 +
build.gradle.kts | 6 +
gradle.properties | 15 +
gradle/gradle-daemon-jvm.properties | 12 +
gradle/libs.versions.toml | 40 +
gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 45457 bytes
gradle/wrapper/gradle-wrapper.properties | 9 +
gradlew | 251 ++++
gradlew.bat | 94 ++
settings.gradle.kts | 26 +
69 files changed, 9281 insertions(+)
create mode 100644 .github/workflows/android.yml
create mode 100644 ScrcpyForAndroid.code-workspace
create mode 100644 app/.gitignore
create mode 100644 app/build.gradle.kts
create mode 100644 app/proguard-rules.pro
create mode 100644 app/src/androidTest/java/io/github/miuzarte/scrcpyforandroid/ExampleInstrumentedTest.kt
create mode 100644 app/src/main/AndroidManifest.xml
create mode 100644 app/src/main/assets/bin/scrcpy-server-v3.3.4
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/MainActivity.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/NativeCoreFacade.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppDefaults.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppPreferenceKeys.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/ScrcpyPresets.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/UiAndroidKeycodes.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/UiMotion.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/UiSpacing.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/haptics/AppHaptics.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/models/DeviceModels.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AnnexBDecoder.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbClient.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/NativeAdbService.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/ScrcpyAudioPlayer.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/ScrcpySessionManager.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/AdvancedConfigPage.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DevicePage.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FullscreenControlPage.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/MainPage.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/SettingsPage.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/VirtualButtonOrderPage.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/PageLayouts.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperSlide.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppSettingsStore.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceConnectionLogic.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/QuickDeviceStore.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/DeviceWidgets.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/SectionSmallTitle.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/SortableCardList.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/StatusCardModels.kt
create mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/VirtualButtons.kt
create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml
create mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml
create mode 100644 app/src/main/res/mipmap-anydpi/ic_launcher.xml
create mode 100644 app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp
create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp
create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp
create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
create mode 100644 app/src/main/res/values-night/themes.xml
create mode 100644 app/src/main/res/values/colors.xml
create mode 100644 app/src/main/res/values/strings.xml
create mode 100644 app/src/main/res/values/themes.xml
create mode 100644 app/src/main/res/xml/backup_rules.xml
create mode 100644 app/src/main/res/xml/data_extraction_rules.xml
create mode 100644 app/src/test/java/io/github/miuzarte/scrcpyforandroid/ExampleUnitTest.kt
create mode 100644 build.gradle.kts
create mode 100644 gradle.properties
create mode 100644 gradle/gradle-daemon-jvm.properties
create mode 100644 gradle/libs.versions.toml
create mode 100644 gradle/wrapper/gradle-wrapper.jar
create mode 100644 gradle/wrapper/gradle-wrapper.properties
create mode 100644 gradlew
create mode 100644 gradlew.bat
create mode 100644 settings.gradle.kts
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
new file mode 100644
index 0000000..9f2f4fa
--- /dev/null
+++ b/.github/workflows/android.yml
@@ -0,0 +1,218 @@
+name: Android Build and Release
+
+on:
+ workflow_dispatch:
+ push:
+ tags:
+ - "*"
+
+permissions:
+ contents: write
+
+jobs:
+ ci-build:
+ if: ${{ github.event_name == 'workflow_dispatch' }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: true
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: "21"
+ distribution: "temurin"
+ cache: gradle
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ !~/.gradle/caches/build-cache-*
+ key: gradle-deps-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: gradle-deps-
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.gradle/caches/build-cache-*
+ key: gradle-builds-${{ github.sha }}
+ restore-keys: gradle-builds-
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Enable full ABI matrix for CI build
+ run: |
+ perl -0777 -i -pe 's/abiFilters\.add\("armeabi-v7a"\)\s*abiFilters\.add\("arm64-v8a"\)/abiFilters.add("armeabi-v7a")\n abiFilters.add("arm64-v8a")\n abiFilters.add("x86")\n abiFilters.add("x86_64")/s' app/build.gradle.kts
+ perl -0777 -i -pe 's/include\("armeabi-v7a",\s*"arm64-v8a"\)/include("armeabi-v7a", "arm64-v8a", "x86", "x86_64")/s' app/build.gradle.kts
+
+ - name: Build debug and unsigned release APKs
+ run: ./gradlew clean assembleDebug assembleRelease
+
+ - name: Collect CI APKs
+ run: |
+ set -euxo pipefail
+ mkdir -p out
+
+ collect_one() {
+ local src="$1"
+ local pattern="$2"
+ local out_name="$3"
+ local file
+ file=$(find "$src" -type f -name "*$pattern*.apk" | head -n1 || true)
+ if [ -n "$file" ]; then
+ cp "$file" "out/$out_name"
+ fi
+ }
+
+ collect_unsigned_release_one() {
+ local pattern="$1"
+ local out_name="$2"
+ local file
+ file=$(find app/build/outputs/apk/release -type f -name "*unsigned*.apk" -name "*$pattern*.apk" | head -n1 || true)
+ if [ -n "$file" ]; then
+ cp "$file" "out/$out_name"
+ fi
+ }
+
+ collect_one app/build/outputs/apk/debug universal ci-debug-arm_all.apk
+ collect_one app/build/outputs/apk/debug arm64-v8a ci-debug-arm64.apk
+ collect_one app/build/outputs/apk/debug armeabi-v7a ci-debug-arm32.apk
+ collect_one app/build/outputs/apk/debug x86_64 ci-debug-x86_64.apk
+ x86_32_debug=$(find app/build/outputs/apk/debug -type f -name "*x86*.apk" ! -name "*x86_64*" | head -n1 || true)
+ if [ -n "$x86_32_debug" ]; then
+ cp "$x86_32_debug" out/ci-debug-x86_32.apk
+ fi
+
+ collect_unsigned_release_one universal ci-release-unsigned-arm_all.apk
+ collect_unsigned_release_one arm64-v8a ci-release-unsigned-arm64.apk
+ collect_unsigned_release_one armeabi-v7a ci-release-unsigned-arm32.apk
+ collect_unsigned_release_one x86_64 ci-release-unsigned-x86_64.apk
+ x86_32_release=$(find app/build/outputs/apk/release -type f -name "*unsigned*.apk" -name "*x86*.apk" ! -name "*x86_64*" | head -n1 || true)
+ if [ -n "$x86_32_release" ]; then
+ cp "$x86_32_release" out/ci-release-unsigned-x86_32.apk
+ fi
+
+ x86_all=$(find app/build/outputs/apk -type f \( -name "*x86_all*.apk" -o -name "*x86-all*.apk" -o -name "*x86universal*.apk" \) | head -n1 || true)
+ if [ -n "$x86_all" ]; then
+ cp "$x86_all" out/ci-release-unsigned-x86_all.apk
+ fi
+
+ ls -la out
+
+ - name: Upload CI artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: android-ci-apks-${{ github.run_number }}
+ path: out/*.apk
+ if-no-files-found: error
+
+ release-build:
+ if: ${{ startsWith(github.ref, 'refs/tags/') }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: true
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: "21"
+ distribution: "temurin"
+ cache: gradle
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ !~/.gradle/caches/build-cache-*
+ key: gradle-deps-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: gradle-deps-
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.gradle/caches/build-cache-*
+ key: gradle-builds-${{ github.sha }}
+ restore-keys: gradle-builds-
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Enable full ABI matrix for release build
+ run: |
+ perl -0777 -i -pe 's/abiFilters\.add\("armeabi-v7a"\)\s*abiFilters\.add\("arm64-v8a"\)/abiFilters.add("armeabi-v7a")\n abiFilters.add("arm64-v8a")\n abiFilters.add("x86")\n abiFilters.add("x86_64")/s' app/build.gradle.kts
+ perl -0777 -i -pe 's/include\("armeabi-v7a",\s*"arm64-v8a"\)/include("armeabi-v7a", "arm64-v8a", "x86", "x86_64")/s' app/build.gradle.kts
+
+ - name: Build debug and unsigned release APKs
+ run: ./gradlew clean assembleDebug assembleRelease
+
+ - name: Collect release assets
+ run: |
+ set -euxo pipefail
+ TAG="${GITHUB_REF_NAME}"
+ REPO_NAME="${GITHUB_REPOSITORY##*/}"
+ mkdir -p dist
+
+ collect_one() {
+ local src="$1"
+ local pattern="$2"
+ local out_name="$3"
+ local file
+ file=$(find "$src" -type f -name "*$pattern*.apk" | head -n1 || true)
+ if [ -n "$file" ]; then
+ cp "$file" "dist/$out_name"
+ fi
+ }
+
+ collect_unsigned_release_one() {
+ local pattern="$1"
+ local out_name="$2"
+ local file
+ file=$(find app/build/outputs/apk/release -type f -name "*unsigned*.apk" -name "*$pattern*.apk" | head -n1 || true)
+ if [ -n "$file" ]; then
+ cp "$file" "dist/$out_name"
+ fi
+ }
+
+ collect_one app/build/outputs/apk/debug universal "${REPO_NAME}-${TAG}-debug-arm_all.apk"
+ collect_one app/build/outputs/apk/debug arm64-v8a "${REPO_NAME}-${TAG}-debug-arm64.apk"
+ collect_one app/build/outputs/apk/debug armeabi-v7a "${REPO_NAME}-${TAG}-debug-arm32.apk"
+ collect_one app/build/outputs/apk/debug x86_64 "${REPO_NAME}-${TAG}-debug-x86_64.apk"
+ x86_32_debug=$(find app/build/outputs/apk/debug -type f -name "*x86*.apk" ! -name "*x86_64*" | head -n1 || true)
+ if [ -n "$x86_32_debug" ]; then
+ cp "$x86_32_debug" "dist/${REPO_NAME}-${TAG}-debug-x86_32.apk"
+ fi
+
+ collect_unsigned_release_one universal "${REPO_NAME}-${TAG}-release-unsigned-arm_all.apk"
+ collect_unsigned_release_one arm64-v8a "${REPO_NAME}-${TAG}-release-unsigned-arm64.apk"
+ collect_unsigned_release_one armeabi-v7a "${REPO_NAME}-${TAG}-release-unsigned-arm32.apk"
+ collect_unsigned_release_one x86_64 "${REPO_NAME}-${TAG}-release-unsigned-x86_64.apk"
+ x86_32_release=$(find app/build/outputs/apk/release -type f -name "*unsigned*.apk" -name "*x86*.apk" ! -name "*x86_64*" | head -n1 || true)
+ if [ -n "$x86_32_release" ]; then
+ cp "$x86_32_release" "dist/${REPO_NAME}-${TAG}-release-unsigned-x86_32.apk"
+ fi
+
+ x86_all=$(find app/build/outputs/apk -type f \( -name "*x86_all*.apk" -o -name "*x86-all*.apk" -o -name "*x86universal*.apk" \) | head -n1 || true)
+ if [ -n "$x86_all" ]; then
+ cp "$x86_all" "dist/${REPO_NAME}-${TAG}-release-unsigned-x86_all.apk"
+ fi
+
+ ls -la dist
+
+ - name: Publish GitHub Release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ github.ref_name }}
+ name: ${{ github.repository }} ${{ github.ref_name }}
+ generate_release_notes: true
+ files: dist/*.apk
diff --git a/ScrcpyForAndroid.code-workspace b/ScrcpyForAndroid.code-workspace
new file mode 100644
index 0000000..06010f7
--- /dev/null
+++ b/ScrcpyForAndroid.code-workspace
@@ -0,0 +1,19 @@
+{
+ "folders": [
+ {
+ "path": "."
+ },
+ {
+ "path": "../scrcpy"
+ },
+ {
+ "path": "../miuix"
+ },
+ {
+ "path": "../adblib"
+ },
+ {
+ "path": "../KernelSU"
+ }
+ ],
+}
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..c31a956
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,66 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.compose.compiler)
+}
+
+android {
+ namespace = "io.github.miuzarte.scrcpyforandroid"
+ compileSdk {
+ version = release(36) {
+ minorApiLevel = 1
+ }
+ }
+
+ defaultConfig {
+ applicationId = "io.github.miuzarte.scrcpyforandroid"
+ minSdk = 26
+ targetSdk = 36
+ versionCode = 1
+ versionName = "0.0.1"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+ buildFeatures {
+ compose = true
+ }
+ buildToolsVersion = "36.0.0"
+ ndkVersion = "28.2.13676358"
+}
+
+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.compose.ui)
+ implementation(libs.androidx.compose.ui.tooling.preview)
+ implementation(libs.androidx.compose.material3)
+ implementation(libs.androidx.compose.material.icons.extended)
+ implementation(libs.androidx.navigation3.runtime)
+ implementation(libs.material)
+ implementation(libs.miuix)
+ implementation(libs.miuix.icons)
+ implementation(libs.miuix.navigation3.ui)
+
+ testImplementation(libs.junit)
+ androidTestImplementation(platform(libs.androidx.compose.bom))
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso.core)
+ androidTestImplementation(libs.androidx.compose.ui.test.junit4)
+ debugImplementation(libs.androidx.compose.ui.tooling)
+ debugImplementation(libs.androidx.compose.ui.test.manifest)
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/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/src/androidTest/java/io/github/miuzarte/scrcpyforandroid/ExampleInstrumentedTest.kt b/app/src/androidTest/java/io/github/miuzarte/scrcpyforandroid/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..1be3e1b
--- /dev/null
+++ b/app/src/androidTest/java/io/github/miuzarte/scrcpyforandroid/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package io.github.miuzarte.scrcpyforandroid
+
+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("io.github.miuzarte.scrcpyforandroid", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..758ec89
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/bin/scrcpy-server-v3.3.4 b/app/src/main/assets/bin/scrcpy-server-v3.3.4
new file mode 100644
index 0000000000000000000000000000000000000000..89054b7ecfa6735b93ee7b293e91abe7ecd8d26e
GIT binary patch
literal 90980
zcmY(o2Rz%~7eCzAS5>WQYpB>C?a@pJDM=RM9lYaYkelEjhB
z|LNK)MoPl!I;x`fo?ua14+kGl7Y9*0e;0QLQILxPY*vIPj_J#4<}C%KgS?H
z;@|suQVk>T-{E|$xYDKToyxB0r|Q^DCkFm(d$uY{ZWyRX&J}{QWbZayO_G!nk})}d
z_#R&=4CHGab*rQ5TGCQ-cWT)ayDh(%wQvftM7mfzD`-GAbC0GzAs$DuWPH)8P)ZQu
z-TxSnMpmcX5Po7QIQHx!RpI|H`Ink^Gi27cZ@s%ma*Ki}xxKrsudk!8h=XHL!V+mG
zUH{F^QO-nc=abTpQ3Vz6n=OI)<(7Vk~_jvu|doQI|
z8i*S=C*VxSB6?MTq71t;;TEa7l$GfQF|=r
zrCP)Cf@o*{~F>-`{f;ziLF%96UNiZ@>CX5JzA=9#)AUMcDpCM
zc6Wh;T##t(*?9DW#cK5qYuyk<%*^cjQ#WZg~#`2efbNX=k%L0jzVvf6Z&s10KwR((3
zf3l7a+6fJYxDR?jVmZ7R71r*suY8&Wp2}&gYInxN7^8E{lGx74kAmK3Gv{Qh5u_rsP4;XUPP
zoOg4MgsfHhCl&4eUJI$d15B?z5m79~R#FDtZPTaBJYse&BoDEB!26E=%j&aQHsF4a;wIA&l*c}A_C;t5=g~eEp
z?AsymuANYsE!Ei?<^Ges^gPju_ju>{LbEuM*3YB5-#sc4Z<~EyYK_j*B}`U3CxvH!
z{?Que>@=?un$T}5efw*)FP;DR?cPJCfWHFbz%|4E-*=Udm;zSriaV6*7XC+6Y>eIG
z0bB9zpVXJ{HtzbLMP9SKOfdYoFgz
zscdbBcdS(%o0Moy2A)v%Yq=}3-a%a$0WyAt{)^>gj6|GMqTkUZ{e3L5!XfwSFgS?=
z_Ny_7y;Ps>+c@>taXR_mG#qySsoKl&+P-wM2Yz`+I&DW0u=1Ea_sq93`B3Dp9j}Qk
zOZTAuWg=l*^xOzIsVE4EW0H=AuSBH!tC^qtbRPXh&pN2x*V*T-?B6s9GK--zOI$jq
z%krY(KlWlTkajJgUw)jwPdNa3!Mh#aVmh9fESg-t%ThDc{=!vAPyB
zIN8aLap}ExV`DB7?d~yN7aaO=JH4Ka|Gu}jBAM0zV6m?;dM=RhvvzAFtBQ2sIGe3M+z$i+?%Q)x
zz9aYGF-NUmw66udmJ3LnxY>1$Pbz1Qfb@U)N-FyN?-hG9<_I);FeZL&jj1tiRsHMB
zs$3#KU>1JPuE4FA7)tHe_u5@m?hjm*@b7cwYz+1dGSMNpY4F9aQq^`|JmbeY?>l&^
zv)is~VWR^rt)GP?TfY?2mAw
Uhjb*XWE*CM#9g_Gev{}aOySDM^T5;l
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ŕhu8Y%@FGhFErLoLjI!7Xx=
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