diff --git a/.github/workflows/flutter_build.yml b/.github/workflows/flutter_build.yml index 3e0e02b..2323202 100644 --- a/.github/workflows/flutter_build.yml +++ b/.github/workflows/flutter_build.yml @@ -29,19 +29,22 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Install Flutter + - name: Install flutter uses: subosito/flutter-action@v2 with: channel: stable cache: true + - name: Configure flutter + run: flutter config --no-cli-animations --no-analytics >/dev/null + - name: Install doit uses: awalsh128/cache-apt-pkgs-action@v1.4.2 with: packages: python3-doit - - name: Run analyzer - run: doit analyze + - name: Run dart analyzer + run: doit lint:dart - name: Run tests run: doit test @@ -58,16 +61,31 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Install Flutter + - name: Install JDK + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: temurin + + - name: Install flutter uses: subosito/flutter-action@v2 with: channel: stable cache: true + - name: Configure flutter + run: flutter config --no-cli-animations --no-analytics >/dev/null + - name: Install doit uses: awalsh128/cache-apt-pkgs-action@v1.4.2 with: packages: python3-doit + - name: Run dart analyzer + run: doit lint:dart + + - name: Run spotless linter + run: doit lint:kotlin + - name: Build apk run: doit build:apk diff --git a/.gitignore b/.gitignore index 1bd7662..b2969e6 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ app.*.map.json # doit related .doit.db* +/dist diff --git a/_temp_storage/app/.gitignore b/_temp_storage/app/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/_temp_storage/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/_temp_storage/app/build.gradle b/_temp_storage/app/build.gradle deleted file mode 100644 index e2021ed..0000000 --- a/_temp_storage/app/build.gradle +++ /dev/null @@ -1,133 +0,0 @@ -def getManifestVersions = { -> - def manifest = new XmlSlurper().parse(file('src/main/AndroidManifest.xml')) - def versionName = manifest.@'android:versionName'.text() - def versionCode = manifest.@'android:versionCode'.text().toInteger() - return [versionName, versionCode] -} - -def getVersionName = { -> - def (versionName, _) = getManifestVersions() - return versionName -} - -def getVersionCode = { -> - def (_, versionCode) = getManifestVersions() - return versionCode -} - -def validateVersion = { -> - def (versionName, versionCode) = getManifestVersions() - - project.logger.lifecycle("Checking version name and code...") - project.logger.lifecycle("versionName = $versionName") - project.logger.lifecycle("versionCode = $versionCode") - - def gitStdout = new ByteArrayOutputStream() - exec { - commandLine 'git', 'describe', '--tags', '--abbrev=0' - standardOutput = gitStdout - } - def versionGit = gitStdout.toString().trim().replaceAll('v', '') - - if (versionName != versionGit) { - throw new GradleException( - "Mismatched android:versionName in AndroidManifest.xml and git tag: "+ - "versionName = $versionName, "+ - "versionGit = $versionGit") - } - - def expectedCode = 0 - def mult = 1 - versionName.tokenize('.').reverse().each { - expectedCode += it.toInteger() * mult - mult *= 1000 - } - - if (versionCode != expectedCode) { - throw new GradleException( - "Mismatched android:versionName and android:versionCode in AndroidManifest.xml: "+ - "versionName = $versionName, "+ - "versionCode = $versionCode, "+ - "expectedCode = $expectedCode") - } -} - -task checkVersion { - doLast { - validateVersion() - } -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' - -android { - compileSdk project.compileSdkVersion.toInteger() - - ndkVersion project.ndkVersion - - defaultConfig { - applicationId 'org.rocstreaming.rocdroid' - - minSdkVersion project.minSdkVersion.toInteger() - targetSdkVersion project.targetSdkVersion.toInteger() - - versionName getVersionName() - versionCode getVersionCode() - } - - applicationVariants.all { variant -> - variant.outputs.all { - outputFileName = "roc-droid-${versionName}.apk" - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - lintOptions { - abortOnError false - } - - signingConfigs { - release { - if (System.getenv("SIGNING_STORE_FILE") != null) { - storeFile file(System.getenv("SIGNING_STORE_FILE")) - storePassword System.getenv("SIGNING_STORE_PASSWORD") - keyAlias System.getenv("SIGNING_KEY_ALIAS") - keyPassword System.getenv("SIGNING_KEY_PASSWORD") - } - } - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') - - if (System.getenv("SIGNING_STORE_FILE") != null) { - signingConfig signingConfigs.release - } - } - } -} - -dependencies { - implementation 'org.roc-streaming.roctoolkit:roc-android:0.2.1' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.3.0' - implementation 'androidx.activity:activity-ktx:1.2.4' - implementation 'androidx.fragment:fragment-ktx:1.3.6' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'com.google.android.material:material:1.3.0' - implementation 'androidx.viewpager2:viewpager2:1.0.0' - implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' -} diff --git a/_temp_storage/app/gradle.properties b/_temp_storage/app/gradle.properties deleted file mode 100644 index 4b7d882..0000000 --- a/_temp_storage/app/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -compileSdkVersion=29 -targetSdkVersion=29 -minSdkVersion=26 -ndkVersion=25.2.9519653 diff --git a/_temp_storage/build.gradle b/_temp_storage/build.gradle deleted file mode 100644 index 9ff0411..0000000 --- a/_temp_storage/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -buildscript { - ext.kotlin_version = '1.7.21' - - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -plugins { - id "com.diffplug.spotless" version "6.12.0" -} - -allprojects { - repositories { - google() - jcenter() - mavenCentral() - } -} - -spotless { - format 'misc', { - // define the files to apply `misc` to - target '**/*.gradle', '**/*.md', '**/.gitignore' - - // define the steps to apply to those files - indentWithSpaces() - trimTrailingWhitespace() - endWithNewline() - } - - kotlin { - target '**/*.kt' - ktlint() - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - } -} diff --git a/_temp_storage/gradle.properties b/_temp_storage/gradle.properties deleted file mode 100644 index 23339e0..0000000 --- a/_temp_storage/gradle.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true -# Automatically convert third-party libraries to use AndroidX -android.enableJetifier=true -# Kotlin code style for this project: "official" or "obsolete": -kotlin.code.style=official diff --git a/_temp_storage/gradle/wrapper/gradle-wrapper.jar b/_temp_storage/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index f6b961f..0000000 Binary files a/_temp_storage/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/_temp_storage/gradle/wrapper/gradle-wrapper.properties b/_temp_storage/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 0e87abc..0000000 --- a/_temp_storage/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sun May 31 15:05:46 MSK 2020 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip diff --git a/_temp_storage/settings.gradle b/_temp_storage/settings.gradle deleted file mode 100644 index ac561b5..0000000 --- a/_temp_storage/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name='roc-droid' -include ':app' diff --git a/android/.gitignore b/android/.gitignore index 6f56801..8eaf34c 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -1,9 +1,7 @@ -gradle-wrapper.jar /.gradle /captures/ -/gradlew -/gradlew.bat /local.properties +/build GeneratedPluginRegistrant.java # Remember to never publicly share your keystore. diff --git a/android/app/build.gradle b/android/app/build.gradle index 6d6784d..2d64f2e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,5 @@ +import org.yaml.snakeyaml.Yaml + plugins { id "com.android.application" id "kotlin-android" @@ -23,56 +25,100 @@ if (flutterVersionName == null) { flutterVersionName = "1.0" } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +def readPubspecVersion = { -> + def pubspec = new Yaml().load(file("../../pubspec.yaml").text) + return pubspec.version +} + +def readManifestVersion = { -> + def manifest = new XmlSlurper().parse(file("src/main/AndroidManifest.xml")) + return manifest.@"android:versionName".text() +} + +def readManifestVersionCode = { -> + def manifest = new XmlSlurper().parse(file("src/main/AndroidManifest.xml")) + return manifest.@"android:versionCode".text().toInteger() +} + +def validateVersion = { -> + def pubspecVersion = readPubspecVersion() + def manifestVersion = readManifestVersion() + + project.logger.lifecycle("Checking version name and code...") + project.logger.lifecycle("pubspecVersion = $pubspecVersion") + project.logger.lifecycle("manifestVersion = $manifestVersion") + + if (pubspecVersion != manifestVersion) { + throw new GradleException( + "Mismatched versions in pubspec.yaml and AndroidManifest.xml:"+ + "\n pubspecVersion = $pubspecVersion"+ + "\n manifestVersion = $manifestVersion") + } +} + +apply plugin: "com.android.application" +apply plugin: "kotlin-android" android { namespace = "org.rocstreaming.rocdroid" - compileSdk = flutter.compileSdkVersion + + compileSdk = project.compileSdkVersion.toInteger() ndkVersion = flutter.ndkVersion + defaultConfig { + applicationId = "org.rocstreaming.rocdroid" + + targetSdkVersion = project.targetSdkVersion.toInteger() + minSdkVersion = project.minSdkVersion.toInteger() + + versionName readManifestVersion() + versionCode readManifestVersionCode() + } + compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = "1.8" } - defaultConfig { - applicationId = "org.rocstreaming.rocdroid" - // You can update the following values to match your application needs. - // For more information, see: - // https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutterVersionCode.toInteger() - versionName = flutterVersionName - minSdkVersion = 26 + composeOptions { + kotlinCompilerExtensionVersion "1.4.0" + } + + lintOptions { + abortOnError false } - applicationVariants.all { variant -> - variant.outputs.all { - outputFileName = "roc-droid.apk" + signingConfigs { + release { + if (System.getenv("SIGNING_STORE_FILE") != null) { + storeFile file(System.getenv("SIGNING_STORE_FILE")) + storePassword System.getenv("SIGNING_STORE_PASSWORD") + keyAlias System.getenv("SIGNING_KEY_ALIAS") + keyPassword System.getenv("SIGNING_KEY_PASSWORD") + } } } buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug + shrinkResources true + minifyEnabled true + proguardFiles getDefaultProguardFile("proguard-android-optimize.txt") + + if (System.getenv("SIGNING_STORE_FILE") != null) { + signingConfig signingConfigs.release + } } } // https://android.izzysoft.de/articles/named/iod-scan-apkchecks#blobs // https://gist.github.com/obfusk/31c332b884464cd8aa06ce1ba1583c05 dependenciesInfo { - // Disables dependency metadata when building APKs. includeInApk = false - // Disables dependency metadata when building Android App Bundles. includeInBundle = false } } @@ -82,14 +128,28 @@ flutter { } dependencies { - implementation 'org.roc-streaming.roctoolkit:roc-android:0.2.1' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.3.0' - implementation 'androidx.activity:activity-ktx:1.9.2' - implementation 'androidx.fragment:fragment-ktx:1.3.6' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'com.google.android.material:material:1.3.0' - implementation 'androidx.viewpager2:viewpager2:1.0.0' - implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' + // kotlin + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + // androidx + implementation "androidx.core:core-ktx:1.9.0" + implementation "androidx.activity:activity-ktx:1.9.2" + implementation "androidx.fragment:fragment-ktx:1.8.4" + implementation "androidx.appcompat:appcompat:1.1.0" + implementation "androidx.constraintlayout:constraintlayout:2.1.4" + implementation "androidx.viewpager2:viewpager2:1.1.0" + // flutter + implementation "com.google.android.material:material:1.3.0" + implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.25" + // roc + implementation "org.roc-streaming.roctoolkit:roc-android:0.2.1" +} + +task validateVersionTask { + doLast { + validateVersion() + } +} + +tasks.matching { it.name.startsWith("assemble") }.configureEach { + dependsOn validateVersionTask } diff --git a/android/app/gradle.properties b/android/app/gradle.properties new file mode 100644 index 0000000..446173b --- /dev/null +++ b/android/app/gradle.properties @@ -0,0 +1,6 @@ +# android 12 +compileSdkVersion=34 +# android 10 +targetSdkVersion=29 +# android 10 +minSdkVersion=29 diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d7f1759..b93e98e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,10 @@ + + package="org.rocstreaming.rocdroid" + android:versionCode="4000" + android:versionName="0.4.0"> + @@ -14,52 +17,62 @@ - + - - - - - - - - - - + android:label="Roc Droid" + android:name="${applicationName}" + android:icon="@mipmap/launcher_icon"> + + + + + + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + + + + + + + + + + + + + In particular, this is used by the Flutter engine in + io.flutter.plugin.text.ProcessTextPlugin. --> - - - - + + + + + diff --git a/android/app/src/main/java/org/rocstreaming/rocdroid/AndroidConnectorImpl.kt b/android/app/src/main/java/org/rocstreaming/rocdroid/AndroidConnectorImpl.kt index 3db737d..05adf9c 100644 --- a/android/app/src/main/java/org/rocstreaming/rocdroid/AndroidConnectorImpl.kt +++ b/android/app/src/main/java/org/rocstreaming/rocdroid/AndroidConnectorImpl.kt @@ -8,8 +8,6 @@ import android.Manifest import android.media.projection.MediaProjection import android.util.Log import java.net.NetworkInterface -import org.rocstreaming.rocdroid.MainActivity -import org.rocstreaming.rocdroid.StreamingService private const val BAD_SEQUENCE_CODE = "rocdroid.BAD_SEQUENCE" private const val BAD_SEQUENCE_TEXT = "Invalid method invocation sequence" @@ -30,7 +28,7 @@ private const val LOG_TAG = "rocdroid.AndroidConnectorImpl" class AndroidConnectorImpl : AndroidConnector { private var projectionAcquired: Boolean = false - fun getActivity() : MainActivity { + fun getActivity(): MainActivity { return MainActivity.instance } @@ -62,7 +60,8 @@ class AndroidConnectorImpl : AndroidConnector { Log.d(LOG_TAG, "Permission request succeeded") callback(Result.success(true)) - }) + } + ) } override fun requestMicrophone(callback: (Result) -> Unit) { @@ -81,7 +80,8 @@ class AndroidConnectorImpl : AndroidConnector { Log.d(LOG_TAG, "Permission request succeeded") callback(Result.success(true)) - }) + } + ) } override fun acquireProjection(callback: (Result) -> Unit) { @@ -122,7 +122,7 @@ class AndroidConnectorImpl : AndroidConnector { } override fun releaseProjection() { - Log.i(LOG_TAG, "Releasing media projection") + Log.i(LOG_TAG, "Releasing media projection") if (!projectionAcquired) { Log.e(LOG_TAG, "Unpaired acquireProjection/releaseProjection calls") @@ -203,7 +203,8 @@ class AndroidConnectorImpl : AndroidConnector { } if (settings.captureType == AndroidCaptureType.CAPTURE_MIC && - !getActivity().hasPermission(Manifest.permission.RECORD_AUDIO)) { + !getActivity().hasPermission(Manifest.permission.RECORD_AUDIO) + ) { Log.e(LOG_TAG, "Microphone permission must be granted when using CAPTURE_MIC") throw FlutterError(NO_PERMISSION_CODE, NO_PERMISSION_TEXT) } diff --git a/android/app/src/main/java/org/rocstreaming/rocdroid/MainActivity.kt b/android/app/src/main/java/org/rocstreaming/rocdroid/MainActivity.kt index 2b0ab66..6cc3ab9 100644 --- a/android/app/src/main/java/org/rocstreaming/rocdroid/MainActivity.kt +++ b/android/app/src/main/java/org/rocstreaming/rocdroid/MainActivity.kt @@ -14,7 +14,6 @@ import android.media.projection.MediaProjectionManager import android.os.Bundle import android.os.IBinder import android.util.Log -import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResult import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts @@ -22,23 +21,20 @@ import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.engine.FlutterEngine -import org.rocstreaming.rocdroid.AndroidConnectorImpl -import org.rocstreaming.rocdroid.StreamingEventListener -import org.rocstreaming.rocdroid.StreamingService private const val LOG_TAG = "rocdroid.MainActivity" -class MainActivity: FlutterFragmentActivity() { +class MainActivity : FlutterFragmentActivity() { // main activity is a singleton used by AndroidConnectorImpl companion object { - lateinit var instance : MainActivity + lateinit var instance: MainActivity } // non-null once successfully connected to server // may temporarily become null when connection is lost private var service: StreamingService? = null - fun getService() : StreamingService? { + fun getService(): StreamingService? { return service } @@ -68,8 +64,10 @@ class MainActivity: FlutterFragmentActivity() { // AndroidConnector interface is generated by pigeon and is called from dart // AndroidConnectorImpl implements its methods // here we link them together - AndroidConnector.setUp(flutterEngine.dartExecutor.binaryMessenger, - AndroidConnectorImpl()) + AndroidConnector.setUp( + flutterEngine.dartExecutor.binaryMessenger, + AndroidConnectorImpl() + ) // AndroidListener class is generated by pigeon and allows kotlin to // invoke dart methods @@ -86,12 +84,16 @@ class MainActivity: FlutterFragmentActivity() { // setup for permission requests permissionRequestLauncher = registerForActivityResult( - ActivityResultContracts.RequestPermission(), this::onPermissionResult) + ActivityResultContracts.RequestPermission(), + this::onPermissionResult + ) // setup for projection request projectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager projectionRequestLauncher = registerForActivityResult( - ActivityResultContracts.StartActivityForResult(), this::onProjectionResult) + ActivityResultContracts.StartActivityForResult(), + this::onProjectionResult + ) } // when app is resumed @@ -127,7 +129,7 @@ class MainActivity: FlutterFragmentActivity() { serviceStartedCallback = callback val serviceIntent = Intent(this, StreamingService::class.java) - startForegroundService(serviceIntent); + startForegroundService(serviceIntent) bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE) } @@ -174,7 +176,7 @@ class MainActivity: FlutterFragmentActivity() { // (re)start & reconnect Log.d(LOG_TAG, "Initiating asynchronous reconnect") val serviceIntent = Intent(this@MainActivity, StreamingService::class.java) - startForegroundService(serviceIntent); + startForegroundService(serviceIntent) bindService(serviceIntent, this, BIND_AUTO_CREATE) } } @@ -190,12 +192,12 @@ class MainActivity: FlutterFragmentActivity() { private fun onProjectionResult(result: ActivityResult) { if (result.data != null) { - Log.d(LOG_TAG, "Media projection acquired with code " + result.resultCode.toString()); + Log.d(LOG_TAG, "Media projection acquired with code " + result.resultCode.toString()) val projection = projectionManager.getMediaProjection(result.resultCode, result.data!!) projectionRequestCallback?.invoke(projection) projectionRequestCallback = null } else { - Log.d(LOG_TAG, "Media projection rejected with code " + result.resultCode.toString()); + Log.d(LOG_TAG, "Media projection rejected with code " + result.resultCode.toString()) projectionRequestCallback?.invoke(null) projectionRequestCallback = null } @@ -239,9 +241,9 @@ class MainActivity: FlutterFragmentActivity() { private fun onPermissionResult(isGranted: Boolean) { if (isGranted) { - Log.d(LOG_TAG, "Permission is granted"); + Log.d(LOG_TAG, "Permission is granted") } else { - Log.w(LOG_TAG, "Permission is rejected"); + Log.w(LOG_TAG, "Permission is rejected") } permissionRequestCallback?.invoke(isGranted) permissionRequestCallback = null diff --git a/android/app/src/main/java/org/rocstreaming/rocdroid/StreamingService.kt b/android/app/src/main/java/org/rocstreaming/rocdroid/StreamingService.kt index 7ac3358..d9acd63 100644 --- a/android/app/src/main/java/org/rocstreaming/rocdroid/StreamingService.kt +++ b/android/app/src/main/java/org/rocstreaming/rocdroid/StreamingService.kt @@ -24,8 +24,6 @@ import android.media.projection.MediaProjection import android.os.Binder import android.os.IBinder import android.util.Log -import org.rocstreaming.rocdroid.MainActivity -import org.rocstreaming.rocdroid.R import org.rocstreaming.roctoolkit.ChannelSet import org.rocstreaming.roctoolkit.ClockSource import org.rocstreaming.roctoolkit.Endpoint @@ -387,16 +385,20 @@ class StreamingService : Service() { sender.connect( Slot.DEFAULT, Interface.AUDIO_SOURCE, - Endpoint(Protocol.RTP_RS8M_SOURCE, - settings.host, - settings.sourcePort.toInt()) + Endpoint( + Protocol.RTP_RS8M_SOURCE, + settings.host, + settings.sourcePort.toInt() + ) ) sender.connect( Slot.DEFAULT, Interface.AUDIO_REPAIR, - Endpoint(Protocol.RS8M_REPAIR, - settings.host, - settings.repairPort.toInt()) + Endpoint( + Protocol.RS8M_REPAIR, + settings.host, + settings.repairPort.toInt() + ) ) } catch (e: Exception) { Log.e(LOG_TAG, "Failed to connect sender: " + e.toString()) @@ -456,16 +458,20 @@ class StreamingService : Service() { receiver.bind( Slot.DEFAULT, Interface.AUDIO_SOURCE, - Endpoint(Protocol.RTP_RS8M_SOURCE, - "0.0.0.0", - settings.sourcePort.toInt()) + Endpoint( + Protocol.RTP_RS8M_SOURCE, + "0.0.0.0", + settings.sourcePort.toInt() + ) ) receiver.bind( Slot.DEFAULT, Interface.AUDIO_REPAIR, - Endpoint(Protocol.RS8M_REPAIR, - "0.0.0.0", - settings.repairPort.toInt()) + Endpoint( + Protocol.RS8M_REPAIR, + "0.0.0.0", + settings.repairPort.toInt() + ) ) } catch (e: Exception) { Log.e(LOG_TAG, "Failed to bind receiver: " + e.toString()) @@ -482,7 +488,6 @@ class StreamingService : Service() { } } } - } finally { Log.d(LOG_TAG, "Releasing receiver resources") @@ -654,7 +659,7 @@ class StreamingService : Service() { // when notification is tapped setContentIntent(pendingContentIntent) // when notification is swiped away - setDeleteIntent(pendingDeleteIntent); + setDeleteIntent(pendingDeleteIntent) // don't allow to dimiss notification on lock screen setOngoing(true) // show on lock screen diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml index 2df1a97..3518933 100644 --- a/android/app/src/main/res/values-night-v31/styles.xml +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -1,6 +1,7 @@ - +