mirror of
https://gitlab.com/futo-org/fcast.git
synced 2025-07-29 13:27:00 +00:00
Merge branch 'michael/android' into 'master'
Android update 42 See merge request videostreaming/fcast!17
This commit is contained in:
commit
b0395ecf98
28 changed files with 363 additions and 128 deletions
5
receivers/android/.gitignore
vendored
5
receivers/android/.gitignore
vendored
|
@ -7,9 +7,14 @@
|
|||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
/.idea/*
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
/app/defaultFlavor
|
||||
/app/playstore
|
||||
|
||||
|
|
|
@ -1,7 +1,49 @@
|
|||
buildAndDeployAndroid:
|
||||
stage: buildAndDeployAndroid
|
||||
|
||||
buildAndroidDockerContainer:
|
||||
stage: buildDockerContainers
|
||||
image: docker:20.10.16
|
||||
services:
|
||||
- docker:20.10.16-dind
|
||||
tags:
|
||||
- fcast-instance-runner
|
||||
before_script:
|
||||
- cd receivers/android
|
||||
script:
|
||||
- sh deploy.sh
|
||||
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
|
||||
- docker build -t $CI_REGISTRY/videostreaming/fcast/receiver-android-dev:latest .
|
||||
- docker push $CI_REGISTRY/videostreaming/fcast/receiver-android-dev:latest
|
||||
when: manual
|
||||
|
||||
buildAndroid:
|
||||
stage: buildAndDeployAndroid
|
||||
image: gitlab.futo.org:5050/videostreaming/fcast/receiver-android-dev:latest
|
||||
tags:
|
||||
- fcast-instance-runner
|
||||
variables:
|
||||
ANDROID_VERSION_NAME: "1"
|
||||
ANDROID_VERSION_CODE: "1"
|
||||
before_script:
|
||||
- cd receivers/android
|
||||
script:
|
||||
- echo "Building content..."
|
||||
- ./gradlew --stacktrace assembleRelease -PversionName=$ANDROID_VERSION_NAME -PversionCode=$ANDROID_VERSION_CODE
|
||||
- ./gradlew --stacktrace bundlePlaystoreRelease -PversionName=$ANDROID_VERSION_NAME -PversionCode=$ANDROID_VERSION_CODE
|
||||
- echo $ANDROID_VERSION_CODE > ./fcast-version.txt
|
||||
- mkdir -p /artifacts/$ANDROID_VERSION_CODE
|
||||
- cp -rf ./app/build/outputs/apk/defaultFlavor/release/app-defaultFlavor-release.apk /artifacts/$ANDROID_VERSION_CODE/fcast-release.apk
|
||||
- cp -rf ./app/build/outputs/bundle/playstoreRelease/app-playstore-release.aab /artifacts/$ANDROID_VERSION_CODE/fcast-playstore-release.aab
|
||||
- cp -rf ./fcast-version.txt /artifacts/fcast-version.txt
|
||||
|
||||
# Artifact uploads require artifacts to be in project directory
|
||||
- mkdir -p ./$ANDROID_VERSION_CODE
|
||||
- mv ./app/build/outputs/apk/defaultFlavor/release/app-defaultFlavor-release.apk ./$ANDROID_VERSION_CODE/fcast-release.apk
|
||||
- mv ./app/build/outputs/bundle/playstoreRelease/app-playstore-release.aab ./$ANDROID_VERSION_CODE/fcast-playstore-release.aab
|
||||
artifacts:
|
||||
untracked: false
|
||||
when: on_success
|
||||
access: all
|
||||
expire_in: "30 days"
|
||||
paths:
|
||||
- receivers/android/$ANDROID_VERSION_CODE/fcast-release.apk
|
||||
- receivers/android/$ANDROID_VERSION_CODE/fcast-playstore-release.aab
|
||||
when: manual
|
19
receivers/android/Dockerfile
Normal file
19
receivers/android/Dockerfile
Normal file
|
@ -0,0 +1,19 @@
|
|||
FROM ubuntu:24.04
|
||||
|
||||
# TZ
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV ANDROID_HOME=/Android/Sdk
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -y zip wget tzdata
|
||||
|
||||
RUN apt install -y openjdk-21-jdk
|
||||
RUN wget https://dl.google.com/android/repository/commandlinetools-linux-13114758_latest.zip
|
||||
RUN unzip commandlinetools-linux-13114758_latest.zip
|
||||
RUN mkdir -p $ANDROID_HOME
|
||||
RUN mv /cmdline-tools $ANDROID_HOME
|
||||
|
||||
RUN yes | $ANDROID_HOME/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --licenses
|
||||
RUN $ANDROID_HOME/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --install "platforms;android-36"
|
|
@ -1,7 +1,7 @@
|
|||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.10'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '2.2.0'
|
||||
}
|
||||
|
||||
ext {
|
||||
|
@ -13,19 +13,19 @@ println("Version Name: $currentVersionName")
|
|||
println("Version Code: $currentVersionCode")
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('/opt/key.properties')
|
||||
def keystorePropertiesFile = rootProject.file('/certs/key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.futo.fcast.receiver'
|
||||
compileSdk 34
|
||||
compileSdk 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.futo.fcast.receiver"
|
||||
minSdk 24
|
||||
targetSdk 34
|
||||
targetSdk 36
|
||||
versionCode currentVersionCode
|
||||
versionName currentVersionName
|
||||
|
||||
|
@ -69,11 +69,8 @@ android {
|
|||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig true
|
||||
|
@ -84,18 +81,18 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.core:core-ktx:1.12.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.11.0'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2"
|
||||
implementation 'androidx.media3:media3-exoplayer:1.2.0'
|
||||
implementation "com.squareup.okhttp3:okhttp:4.11.0"
|
||||
implementation 'androidx.core:core-ktx:1.16.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.1'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
|
||||
implementation 'androidx.media3:media3-exoplayer:1.7.1'
|
||||
implementation "com.squareup.okhttp3:okhttp:5.1.0"
|
||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
|
||||
implementation 'org.java-websocket:Java-WebSocket:1.5.4'
|
||||
implementation 'androidx.media3:media3-ui:1.2.0'
|
||||
implementation 'androidx.media3:media3-exoplayer-dash:1.2.0'
|
||||
implementation 'androidx.media3:media3-exoplayer-hls:1.2.0'
|
||||
implementation 'org.java-websocket:Java-WebSocket:1.6.0'
|
||||
implementation 'androidx.media3:media3-ui:1.7.1'
|
||||
implementation 'androidx.media3:media3-exoplayer-dash:1.7.1'
|
||||
implementation 'androidx.media3:media3-exoplayer-hls:1.7.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class BootReceiver : BroadcastReceiver() {
|
|||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// Show a notification with an action to start the service
|
||||
showStartServiceNotification(context);
|
||||
showStartServiceNotification(context)
|
||||
} else {
|
||||
// Directly start the service for older versions
|
||||
val serviceIntent = Intent(context, NetworkService::class.java)
|
||||
|
|
|
@ -4,4 +4,4 @@ import android.content.Context
|
|||
import android.util.AttributeSet
|
||||
import androidx.media3.ui.PlayerView
|
||||
|
||||
class CustomPlayerView(context: Context, attrs: AttributeSet? = null) : PlayerView(context, attrs) { }
|
||||
class CustomPlayerView(context: Context, attrs: AttributeSet? = null) : PlayerView(context, attrs)
|
|
@ -1,6 +1,5 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import WebSocketListenerService
|
||||
import android.content.Context
|
||||
import android.net.nsd.NsdManager
|
||||
import android.net.nsd.NsdServiceInfo
|
||||
|
@ -40,14 +39,14 @@ class DiscoveryService(private val _context: Context) {
|
|||
|
||||
try {
|
||||
_nsdManager?.unregisterService(_registrationListenerTcp)
|
||||
} catch (e: Throwable) {
|
||||
Log.e(TAG, "Failed to unregister TCP Listener.");
|
||||
} catch (_: Throwable) {
|
||||
Log.e(TAG, "Failed to unregister TCP Listener.")
|
||||
}
|
||||
|
||||
try {
|
||||
_nsdManager?.unregisterService(_registrationListenerWs)
|
||||
} catch (e: Throwable) {
|
||||
Log.e(TAG, "Failed to unregister TCP Listener.");
|
||||
} catch (_: Throwable) {
|
||||
Log.e(TAG, "Failed to unregister TCP Listener.")
|
||||
}
|
||||
|
||||
_nsdManager = null
|
||||
|
|
|
@ -1,27 +1,13 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.DataOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.math.BigInteger
|
||||
import java.net.SocketAddress
|
||||
import java.nio.ByteBuffer
|
||||
import java.security.KeyFactory
|
||||
import java.security.KeyPair
|
||||
import java.security.KeyPairGenerator
|
||||
import java.security.MessageDigest
|
||||
import java.security.PrivateKey
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.util.UUID
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.KeyAgreement
|
||||
import javax.crypto.spec.DHParameterSpec
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
|
||||
|
||||
enum class SessionState {
|
||||
|
@ -48,8 +34,8 @@ enum class Opcode(val value: Byte) {
|
|||
Pong(13);
|
||||
|
||||
companion object {
|
||||
private val _map = values().associateBy { it.value }
|
||||
fun find(value: Byte): Opcode = _map[value] ?: Opcode.None
|
||||
private val _map = entries.associateBy { it.value }
|
||||
fun find(value: Byte): Opcode = _map[value] ?: None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +97,7 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress:
|
|||
}
|
||||
|
||||
fun processBytes(data: ByteBuffer) {
|
||||
Log.i(TAG, "${data.remaining()} bytes received from ${_remoteSocketAddress}")
|
||||
Log.i(TAG, "${data.remaining()} bytes received from $_remoteSocketAddress")
|
||||
if (!data.hasArray()) {
|
||||
throw IllegalArgumentException("ByteBuffer does not have a backing array")
|
||||
}
|
||||
|
@ -132,7 +118,7 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress:
|
|||
return
|
||||
}
|
||||
|
||||
Log.i(TAG, "$count bytes received from ${_remoteSocketAddress}")
|
||||
Log.i(TAG, "$count bytes received from $_remoteSocketAddress")
|
||||
|
||||
when (_state) {
|
||||
SessionState.WaitingForLength -> handleLengthBytes(data, 0, count)
|
||||
|
@ -166,7 +152,7 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress:
|
|||
}
|
||||
|
||||
if (bytesRemaining > 0) {
|
||||
Log.i(TAG, "$bytesRemaining remaining bytes ${_remoteSocketAddress} pushed to handlePacketBytes")
|
||||
Log.i(TAG, "$bytesRemaining remaining bytes $_remoteSocketAddress pushed to handlePacketBytes")
|
||||
handlePacketBytes(data, offset + bytesToRead, bytesRemaining)
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +167,7 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress:
|
|||
Log.i(TAG, "Read $bytesToRead bytes from packet")
|
||||
|
||||
if (_bytesRead >= _packetLength) {
|
||||
Log.i(TAG, "Packet finished receiving from ${_remoteSocketAddress} of $_packetLength bytes.")
|
||||
Log.i(TAG, "Packet finished receiving from $_remoteSocketAddress of $_packetLength bytes.")
|
||||
handleNextPacket()
|
||||
|
||||
_state = SessionState.WaitingForLength
|
||||
|
@ -189,14 +175,14 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress:
|
|||
_bytesRead = 0
|
||||
|
||||
if (bytesRemaining > 0) {
|
||||
Log.i(TAG, "$bytesRemaining remaining bytes ${_remoteSocketAddress} pushed to handleLengthBytes")
|
||||
Log.i(TAG, "$bytesRemaining remaining bytes $_remoteSocketAddress pushed to handleLengthBytes")
|
||||
handleLengthBytes(data, offset + bytesToRead, bytesRemaining)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleNextPacket() {
|
||||
Log.i(TAG, "Processing packet of $_bytesRead bytes from ${_remoteSocketAddress}")
|
||||
Log.i(TAG, "Processing packet of $_bytesRead bytes from $_remoteSocketAddress")
|
||||
|
||||
val opcode = Opcode.find(_buffer[0])
|
||||
val body = if (_packetLength > 1) _buffer.copyOfRange(1, _packetLength)
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import WebSocketListenerService
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
|
@ -34,12 +30,12 @@ import androidx.media3.ui.PlayerView
|
|||
import com.google.zxing.BarcodeFormat
|
||||
import com.journeyapps.barcodescanner.BarcodeEncoder
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.OkHttpClient
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.NetworkInterface
|
||||
import androidx.core.net.toUri
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
@ -153,7 +149,7 @@ class MainActivity : AppCompatActivity() {
|
|||
Log.i(TAG, "connection url: $url")
|
||||
val bitmap = barcodeEncoder.encodeBitmap(url, BarcodeFormat.QR_CODE, px, px)
|
||||
_imageQr.setImageBitmap(bitmap)
|
||||
} catch (e: java.lang.Exception) {
|
||||
} catch (_: java.lang.Exception) {
|
||||
_textScanToConnect.visibility = View.GONE
|
||||
_imageQr.visibility = View.GONE
|
||||
}
|
||||
|
@ -201,7 +197,7 @@ class MainActivity : AppCompatActivity() {
|
|||
_player = ExoPlayer.Builder(this).build()
|
||||
_videoBackground.player = _player
|
||||
|
||||
val mediaItem = MediaItem.fromUri(Uri.parse("android.resource://" + packageName + "/" + R.raw.c))
|
||||
val mediaItem = MediaItem.fromUri(("android.resource://" + packageName + "/" + R.raw.c).toUri())
|
||||
_player.setMediaItem(mediaItem)
|
||||
_player.prepare()
|
||||
_player.repeatMode = Player.REPEAT_MODE_ALL
|
||||
|
@ -224,7 +220,7 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
if (listPermissionsNeeded.isNotEmpty()) {
|
||||
val permissionRequestedKey = "NOTIFICATIONS_PERMISSION_REQUESTED"
|
||||
val sharedPref = this.getSharedPreferences(_preferenceFileKey, Context.MODE_PRIVATE)
|
||||
val sharedPref = this.getSharedPreferences(_preferenceFileKey, MODE_PRIVATE)
|
||||
val hasRequestedPermission = sharedPref.getBoolean(permissionRequestedKey, false)
|
||||
if (!hasRequestedPermission) {
|
||||
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toTypedArray(), REQUEST_ID_MULTIPLE_PERMISSIONS)
|
||||
|
@ -244,7 +240,7 @@ class MainActivity : AppCompatActivity() {
|
|||
private fun requestSystemAlertWindowPermission() {
|
||||
try {
|
||||
val permissionRequestedKey = "SYSTEM_ALERT_WINDOW_PERMISSION_REQUESTED"
|
||||
val sharedPref = this.getSharedPreferences(_preferenceFileKey, Context.MODE_PRIVATE)
|
||||
val sharedPref = this.getSharedPreferences(_preferenceFileKey, MODE_PRIVATE)
|
||||
val hasRequestedPermission = sharedPref.getBoolean(permissionRequestedKey, false)
|
||||
|
||||
if (!Settings.canDrawOverlays(this)) {
|
||||
|
@ -254,7 +250,8 @@ class MainActivity : AppCompatActivity() {
|
|||
.setMessage(R.string.permission_dialog_message)
|
||||
.setPositiveButton(R.string.permission_dialog_positive_button) { _, _ ->
|
||||
try {
|
||||
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName"))
|
||||
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||
"package:$packageName".toUri())
|
||||
_systemAlertWindowPermissionLauncher.launch(intent)
|
||||
} catch (e: Throwable) {
|
||||
Log.e("OverlayPermission", "Error requesting overlay permission", e)
|
||||
|
@ -276,7 +273,7 @@ class MainActivity : AppCompatActivity() {
|
|||
Toast.makeText(this, "Optional system alert window permission missing", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
} catch (_: Throwable) {
|
||||
Log.e(TAG, "Failed to request system alert window permissions")
|
||||
}
|
||||
}
|
||||
|
@ -367,7 +364,7 @@ class MainActivity : AppCompatActivity() {
|
|||
_updateSpinner.visibility = View.INVISIBLE
|
||||
setText(resources.getText(R.string.there_is_an_update_available_do_you_wish_to_update))
|
||||
_buttonUpdate.visibility = View.VISIBLE
|
||||
} catch (e: Throwable) {
|
||||
} catch (_: Throwable) {
|
||||
Toast.makeText(this@MainActivity, "Failed to show update dialog", Toast.LENGTH_LONG).show()
|
||||
Log.w(TAG, "Error occurred in update dialog.")
|
||||
}
|
||||
|
@ -388,11 +385,11 @@ class MainActivity : AppCompatActivity() {
|
|||
.build()
|
||||
|
||||
val response = client.newCall(request).execute()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
if (!response.isSuccessful) {
|
||||
return null
|
||||
}
|
||||
|
||||
return response.body?.string()?.trim()?.toInt()
|
||||
return response.body.string().trim().toInt()
|
||||
}
|
||||
|
||||
private fun update() {
|
||||
|
@ -414,7 +411,7 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
val response = client.newCall(request).execute()
|
||||
val body = response.body
|
||||
if (response.isSuccessful && body != null) {
|
||||
if (response.isSuccessful) {
|
||||
inputStream = body.byteStream()
|
||||
val dataLength = body.contentLength()
|
||||
install(inputStream, dataLength)
|
||||
|
@ -540,8 +537,8 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
companion object {
|
||||
const val TAG = "MainActivity"
|
||||
const val VERSION_URL = "https://releases.grayjay.app/fcast-version.txt"
|
||||
const val APK_URL = "https://releases.grayjay.app/fcast-release.apk"
|
||||
const val VERSION_URL = "https://dl.fcast.org/android/fcast-version.txt"
|
||||
const val APK_URL = "https://dl.fcast.org/android/fcast-release.apk"
|
||||
const val REQUEST_ID_MULTIPLE_PERMISSIONS = 1
|
||||
const val REQUEST_CODE = 2
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import WebSocketListenerService
|
||||
import android.app.*
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
|
@ -10,10 +8,8 @@ import android.os.IBinder
|
|||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class NetworkService : Service() {
|
||||
|
@ -48,7 +44,7 @@ class NetworkService : Service() {
|
|||
description = descriptionText
|
||||
}
|
||||
|
||||
val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val notificationManager: NotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
|
@ -72,7 +68,7 @@ class NetworkService : Service() {
|
|||
try {
|
||||
Log.i(TAG, "Sending version ${session.id}")
|
||||
session.send(Opcode.Version, VersionMessage(2))
|
||||
} catch (e: Throwable) {
|
||||
} catch (_: Throwable) {
|
||||
Log.e(TAG, "Failed to send version ${session.id}")
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +118,7 @@ class NetworkService : Service() {
|
|||
|
||||
try {
|
||||
_webSocketListenerService?.stop()
|
||||
} catch (e: Throwable) {
|
||||
} catch (_: Throwable) {
|
||||
//Ignored
|
||||
} finally {
|
||||
_webSocketListenerService = null
|
||||
|
@ -193,7 +189,7 @@ class NetworkService : Service() {
|
|||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.notify(PLAY_NOTIFICATION_ID, playNotification)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
|
@ -44,6 +43,7 @@ import java.io.File
|
|||
import java.io.FileOutputStream
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import androidx.core.net.toUri
|
||||
|
||||
|
||||
class PlayerActivity : AppCompatActivity() {
|
||||
|
@ -245,7 +245,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||
_playerControlView.controllerAutoShow = false
|
||||
|
||||
Log.i(TAG, "Attached onConnectionAvailable listener.")
|
||||
_connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
_connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val netReq = NetworkRequest.Builder()
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
|
@ -398,7 +398,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
if (!playMessage.url.isNullOrEmpty()) {
|
||||
mediaItemBuilder.setUri(Uri.parse(playMessage.url))
|
||||
mediaItemBuilder.setUri(playMessage.url.toUri())
|
||||
} else if (!playMessage.content.isNullOrEmpty()) {
|
||||
val tempFile = File.createTempFile("content_", ".tmp", cacheDir)
|
||||
tempFile.deleteOnExit()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import android.util.Log
|
||||
import java.io.BufferedInputStream
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.ServerSocket
|
||||
import java.net.Socket
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import android.util.Log
|
||||
import com.futo.fcast.receiver.FCastSession
|
||||
import com.futo.fcast.receiver.NetworkService
|
||||
import org.java_websocket.WebSocket
|
||||
import org.java_websocket.handshake.ClientHandshake
|
||||
import org.java_websocket.server.WebSocketServer
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
package com.futo.fcast.receiver
|
||||
|
||||
import org.java_websocket.WebSocket
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
|
25
receivers/android/app/src/main/res/values-ar/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-ar/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">جهاز استقبال FCast</string>
|
||||
<string name="general_failure">فشلت العملية بشكل عام</string>
|
||||
<string name="aborted">فشلت العملية بسبب إلغائها بشكل نشط</string>
|
||||
<string name="blocked">فشلت العملية بسبب حظرها</string>
|
||||
<string name="conflict">فشلت العملية لأنها تتعارض (أو غير متوافقة مع) حزمة أخرى مثبتة بالفعل على الجهاز</string>
|
||||
<string name="incompatible">فشلت العملية لأنها غير متوافقة بشكل أساسي مع هذا الجهاز</string>
|
||||
<string name="invalid">فشلت العملية لأن أحد ملفات APK أو أكثر كان غير صالح</string>
|
||||
<string name="not_enough_storage">فشلت العملية بسبب مشاكل التخزين</string>
|
||||
<string name="downloading_update">جاري تنزيل التحديث…</string>
|
||||
<string name="installing_update">جاري تثبيت التحديث…</string>
|
||||
<string name="success">نجاح</string>
|
||||
<string name="failed_to_update_with_error">فشل تحديث الحزمة بسبب الخطأ</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">هناك تحديث متاح لجهاز الاستقبال FCast، هل ترغب في التحديث؟</string>
|
||||
<string name="never">أبداً</string>
|
||||
<string name="close">يغلق</string>
|
||||
<string name="update">تحديث</string>
|
||||
<string name="checking_for_updates">التحقق من التحديثات…</string>
|
||||
<string name="no_updates_available">لا توجد تحديثات متاحة</string>
|
||||
<string name="permission_dialog_title">إذن نافذة تنبيه النظام</string>
|
||||
<string name="permission_dialog_message">يتطلب هذا التطبيق إذن "نافذة تنبيه النظام" لعرض المحتوى فوق التطبيقات الأخرى. يُرجى منح الإذن.</string>
|
||||
<string name="permission_dialog_positive_button">يسمح</string>
|
||||
<string name="permission_dialog_negative_button">يلغي</string>
|
||||
<string name="waiting_for_media">في انتظار وسائل الإعلام</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-de/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-de/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">FCast-Empfänger</string>
|
||||
<string name="general_failure">Der Vorgang ist auf allgemeine Weise fehlgeschlagen</string>
|
||||
<string name="aborted">Der Vorgang ist fehlgeschlagen, da er aktiv abgebrochen wurde</string>
|
||||
<string name="blocked">Der Vorgang ist fehlgeschlagen, weil er blockiert wurde</string>
|
||||
<string name="conflict">Der Vorgang ist fehlgeschlagen, da er mit einem anderen Paket, das bereits auf dem Gerät installiert ist, in Konflikt steht (oder inkonsistent ist).</string>
|
||||
<string name="incompatible">Der Vorgang ist fehlgeschlagen, da er grundsätzlich nicht mit diesem Gerät kompatibel ist</string>
|
||||
<string name="invalid">Der Vorgang ist fehlgeschlagen, da eine oder mehrere APKs ungültig waren</string>
|
||||
<string name="not_enough_storage">Der Vorgang ist aufgrund von Speicherproblemen fehlgeschlagen</string>
|
||||
<string name="downloading_update">Update wird heruntergeladen…</string>
|
||||
<string name="installing_update">Update wird installiert…</string>
|
||||
<string name="success">Erfolg</string>
|
||||
<string name="failed_to_update_with_error">Paket konnte nicht aktualisiert werden. Fehler</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">Für den FCast-Receiver ist ein Update verfügbar. Möchten Sie ein Update durchführen?</string>
|
||||
<string name="never">Niemals</string>
|
||||
<string name="close">Schließen</string>
|
||||
<string name="update">Aktualisieren</string>
|
||||
<string name="checking_for_updates">Suche nach Updates…</string>
|
||||
<string name="no_updates_available">Keine Updates verfügbar</string>
|
||||
<string name="permission_dialog_title">Berechtigung für das Systemwarnungsfenster</string>
|
||||
<string name="permission_dialog_message">Diese App benötigt die Berechtigung „Systemwarnfenster“, um Inhalte über anderen Apps anzuzeigen. Bitte erteilen Sie die Berechtigung.</string>
|
||||
<string name="permission_dialog_positive_button">Erlauben</string>
|
||||
<string name="permission_dialog_negative_button">Stornieren</string>
|
||||
<string name="waiting_for_media">Warten auf Medien</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-es/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-es/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">Receptor FCast</string>
|
||||
<string name="general_failure">La operación falló de forma genérica</string>
|
||||
<string name="aborted">La operación falló porque fue abortada activamente.</string>
|
||||
<string name="blocked">La operación falló porque fue bloqueada</string>
|
||||
<string name="conflict">La operación falló porque entra en conflicto (o es inconsistente) con otro paquete ya instalado en el dispositivo</string>
|
||||
<string name="incompatible">La operación falló porque es fundamentalmente incompatible con este dispositivo.</string>
|
||||
<string name="invalid">La operación falló porque uno o más de los APK no eran válidos</string>
|
||||
<string name="not_enough_storage">La operación falló debido a problemas de almacenamiento.</string>
|
||||
<string name="downloading_update">Descargando actualización…</string>
|
||||
<string name="installing_update">Instalando actualización…</string>
|
||||
<string name="success">Éxito</string>
|
||||
<string name="failed_to_update_with_error">No se pudo actualizar el paquete con error</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">Hay una actualización disponible para el receptor FCast, ¿desea actualizar?</string>
|
||||
<string name="never">Nunca</string>
|
||||
<string name="close">Cerca</string>
|
||||
<string name="update">Actualizar</string>
|
||||
<string name="checking_for_updates">Buscando actualizaciones…</string>
|
||||
<string name="no_updates_available">No hay actualizaciones disponibles</string>
|
||||
<string name="permission_dialog_title">Permiso de la ventana de alerta del sistema</string>
|
||||
<string name="permission_dialog_message">Esta aplicación requiere el permiso de la ventana de alertas del sistema para mostrar contenido sobre otras aplicaciones. Por favor, concédelo.</string>
|
||||
<string name="permission_dialog_positive_button">Permitir</string>
|
||||
<string name="permission_dialog_negative_button">Cancelar</string>
|
||||
<string name="waiting_for_media">Esperando a los medios</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-fr/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-fr/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">Récepteur FCast</string>
|
||||
<string name="general_failure">L\'opération a échoué de manière générique</string>
|
||||
<string name="aborted">L\'opération a échoué car elle a été activement interrompue</string>
|
||||
<string name="blocked">L\'opération a échoué car elle a été bloquée</string>
|
||||
<string name="conflict">L\'opération a échoué car elle est en conflit (ou est incohérente avec) avec un autre package déjà installé sur l\'appareil</string>
|
||||
<string name="incompatible">L\'opération a échoué car elle est fondamentalement incompatible avec cet appareil</string>
|
||||
<string name="invalid">L\'opération a échoué car un ou plusieurs APK n\'étaient pas valides</string>
|
||||
<string name="not_enough_storage">L\'opération a échoué en raison de problèmes de stockage</string>
|
||||
<string name="downloading_update">Téléchargement de la mise à jour…</string>
|
||||
<string name="installing_update">Installation de la mise à jour…</string>
|
||||
<string name="success">Succès</string>
|
||||
<string name="failed_to_update_with_error">Échec de la mise à jour du package avec erreur</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">Une mise à jour est disponible pour le récepteur FCast, souhaitez-vous effectuer la mise à jour ?</string>
|
||||
<string name="never">Jamais</string>
|
||||
<string name="close">Fermer</string>
|
||||
<string name="update">Mise à jour</string>
|
||||
<string name="checking_for_updates">Vérification des mises à jour…</string>
|
||||
<string name="no_updates_available">Aucune mise à jour disponible</string>
|
||||
<string name="permission_dialog_title">Autorisation de la fenêtre d\'alerte système</string>
|
||||
<string name="permission_dialog_message">Cette application nécessite l\'autorisation de la fenêtre d\'alerte système pour afficher du contenu par-dessus d\'autres applications. Veuillez accorder cette autorisation.</string>
|
||||
<string name="permission_dialog_positive_button">Permettre</string>
|
||||
<string name="permission_dialog_negative_button">Annuler</string>
|
||||
<string name="waiting_for_media">En attente des médias</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-ja/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-ja/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">FCastレシーバー</string>
|
||||
<string name="general_failure">操作は一般的な方法で失敗しました</string>
|
||||
<string name="aborted">操作は強制的に中止されたため失敗しました</string>
|
||||
<string name="blocked">ブロックされたため操作に失敗しました</string>
|
||||
<string name="conflict">デバイスにすでにインストールされている別のパッケージと競合(または矛盾)しているため、操作に失敗しました</string>
|
||||
<string name="incompatible">このデバイスと根本的に互換性がないため、操作は失敗しました</string>
|
||||
<string name="invalid">1 つ以上の APK が無効であったため、操作に失敗しました</string>
|
||||
<string name="not_enough_storage">ストレージの問題により操作が失敗しました</string>
|
||||
<string name="downloading_update">アップデートをダウンロードしています…</string>
|
||||
<string name="installing_update">アップデートをインストールしています…</string>
|
||||
<string name="success">成功</string>
|
||||
<string name="failed_to_update_with_error">エラーのためパッケージの更新に失敗しました</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">FCast レシーバーのアップデートが利用可能です。アップデートしますか?</string>
|
||||
<string name="never">一度もない</string>
|
||||
<string name="close">近い</string>
|
||||
<string name="update">アップデート</string>
|
||||
<string name="checking_for_updates">アップデートを確認しています…</string>
|
||||
<string name="no_updates_available">更新情報はありません</string>
|
||||
<string name="permission_dialog_title">システム警告ウィンドウの権限</string>
|
||||
<string name="permission_dialog_message">このアプリは、他のアプリの上にコンテンツを表示するためにシステムアラートウィンドウの権限が必要です。権限を付与してください。</string>
|
||||
<string name="permission_dialog_positive_button">許可する</string>
|
||||
<string name="permission_dialog_negative_button">キャンセル</string>
|
||||
<string name="waiting_for_media">メディアを待っています</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-ko/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-ko/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">FCast 수신기</string>
|
||||
<string name="general_failure">작업이 일반적인 방식으로 실패했습니다.</string>
|
||||
<string name="aborted">작업이 적극적으로 중단되어 실패했습니다.</string>
|
||||
<string name="blocked">작업이 차단되어 실패했습니다.</string>
|
||||
<string name="conflict">해당 작업은 장치에 이미 설치된 다른 패키지와 충돌하거나 일관성이 없기 때문에 실패했습니다.</string>
|
||||
<string name="incompatible">이 작업은 이 장치와 근본적으로 호환되지 않기 때문에 실패했습니다.</string>
|
||||
<string name="invalid">APK 중 하나 이상이 유효하지 않아 작업이 실패했습니다.</string>
|
||||
<string name="not_enough_storage">저장소 문제로 인해 작업이 실패했습니다.</string>
|
||||
<string name="downloading_update">업데이트를 다운로드하는 중…</string>
|
||||
<string name="installing_update">업데이트를 설치하는 중…</string>
|
||||
<string name="success">성공</string>
|
||||
<string name="failed_to_update_with_error">오류로 인해 패키지를 업데이트하지 못했습니다.</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">FCast 수신기에 대한 업데이트가 있습니다. 업데이트하시겠습니까?</string>
|
||||
<string name="never">절대</string>
|
||||
<string name="close">닫다</string>
|
||||
<string name="update">업데이트</string>
|
||||
<string name="checking_for_updates">업데이트를 확인하는 중…</string>
|
||||
<string name="no_updates_available">업데이트가 없습니다</string>
|
||||
<string name="permission_dialog_title">시스템 알림 창 권한</string>
|
||||
<string name="permission_dialog_message">이 앱은 다른 앱 위에 콘텐츠를 표시하기 위해 시스템 알림 창 권한이 필요합니다. 권한을 부여해 주세요.</string>
|
||||
<string name="permission_dialog_positive_button">허용하다</string>
|
||||
<string name="permission_dialog_negative_button">취소</string>
|
||||
<string name="waiting_for_media">미디어를 기다리는 중</string>
|
||||
</resources>
|
|
@ -7,15 +7,15 @@
|
|||
<string name="incompatible">A operação falhou pois é fundamentalmente incompatível com este dispositivo</string>
|
||||
<string name="invalid">A operação falhou pois um ou mais dos APKs eram inválidos</string>
|
||||
<string name="not_enough_storage">A operação falhou por causa de problemas de armazenamento</string>
|
||||
<string name="downloading_update">Baixando a atualização...</string>
|
||||
<string name="installing_update">Instalando a atualização...</string>
|
||||
<string name="downloading_update">Baixando a atualização…</string>
|
||||
<string name="installing_update">Instalando a atualização…</string>
|
||||
<string name="success">Sucesso</string>
|
||||
<string name="failed_to_update_with_error">Falhou em atualizar pacote com erro</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">Há uma atualização nova para o receptor do FCast, você quer atualizar?</string>
|
||||
<string name="never">Nunca</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="update">Atualizar</string>
|
||||
<string name="checking_for_updates">Buscando atualizações...</string>
|
||||
<string name="checking_for_updates">Buscando atualizações…</string>
|
||||
<string name="no_updates_available">Não há atualizações disponíveis</string>
|
||||
<string name="permission_dialog_title">Sobrepor outros apps</string> <!-- Adapted to just use the translation from AOSP, Display over other apps -->
|
||||
<string name="permission_dialog_message">Este app precisa da permissão para sobrepor outros apps para que possa exibir conteúdo em cima de outros apps. Por favor conceda a permissão.</string>
|
||||
|
|
25
receivers/android/app/src/main/res/values-pt/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-pt/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">Receptor FCast</string>
|
||||
<string name="general_failure">A operação falhou de um modo genérico</string>
|
||||
<string name="aborted">A operação falhou pois foi abortada ativamente</string>
|
||||
<string name="blocked">A operação falhou pois foi bloqueada</string>
|
||||
<string name="conflict">A operação falhou pois conflita (ou é inconsistente) com outro pacote que já está instalado no dispositivo</string>
|
||||
<string name="incompatible">A operação falhou pois é fundamentalmente incompatível com este dispositivo</string>
|
||||
<string name="invalid">A operação falhou pois um ou mais dos APKs eram inválidos</string>
|
||||
<string name="not_enough_storage">A operação falhou por causa de problemas de armazenamento</string>
|
||||
<string name="downloading_update">Baixando a atualização…</string>
|
||||
<string name="installing_update">Instalando a atualização…</string>
|
||||
<string name="success">Sucesso</string>
|
||||
<string name="failed_to_update_with_error">Falhou em atualizar pacote com erro</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">Há uma atualização nova para o receptor do FCast, você quer atualizar?</string>
|
||||
<string name="never">Nunca</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="update">Atualizar</string>
|
||||
<string name="checking_for_updates">Buscando atualizações…</string>
|
||||
<string name="no_updates_available">Não há atualizações disponíveis</string>
|
||||
<string name="permission_dialog_title">Sobrepor outros apps</string> <!-- Adapted to just use the translation from AOSP, Display over other apps -->
|
||||
<string name="permission_dialog_message">Este app precisa da permissão para sobrepor outros apps para que possa exibir conteúdo em cima de outros apps. Por favor conceda a permissão.</string>
|
||||
<string name="permission_dialog_positive_button">Permitir</string>
|
||||
<string name="permission_dialog_negative_button">Cancelar</string>
|
||||
<string name="waiting_for_media">Aguardando mídia</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-ru/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-ru/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">FCast-приемник</string>
|
||||
<string name="general_failure">Операция провалилась в общем виде</string>
|
||||
<string name="aborted">Операция провалилась, потому что ее активно отменили.</string>
|
||||
<string name="blocked">Операция не удалась, так как она была заблокирована</string>
|
||||
<string name="conflict">Операция не выполнена, поскольку она конфликтует (или несовместима) с другим пакетом, уже установленным на устройстве.</string>
|
||||
<string name="incompatible">Операция не удалась, так как она принципиально несовместима с этим устройством.</string>
|
||||
<string name="invalid">Операция не удалась, так как один или несколько APK-файлов оказались недействительными.</string>
|
||||
<string name="not_enough_storage">Операция не удалась из-за проблем с хранением</string>
|
||||
<string name="downloading_update">Загрузка обновления…</string>
|
||||
<string name="installing_update">Установка обновления…</string>
|
||||
<string name="success">Успех</string>
|
||||
<string name="failed_to_update_with_error">Не удалось обновить пакет из-за ошибки</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">Доступно обновление для приемника FCast. Хотите обновиться?</string>
|
||||
<string name="never">Никогда</string>
|
||||
<string name="close">Закрывать</string>
|
||||
<string name="update">Обновлять</string>
|
||||
<string name="checking_for_updates">Проверка обновлений…</string>
|
||||
<string name="no_updates_available">Нет доступных обновлений</string>
|
||||
<string name="permission_dialog_title">Разрешение окна системного оповещения</string>
|
||||
<string name="permission_dialog_message">Этому приложению требуется разрешение System Alert Window для отображения контента поверх других приложений. Пожалуйста, предоставьте разрешение.</string>
|
||||
<string name="permission_dialog_positive_button">Позволять</string>
|
||||
<string name="permission_dialog_negative_button">Отмена</string>
|
||||
<string name="waiting_for_media">Ожидание СМИ</string>
|
||||
</resources>
|
25
receivers/android/app/src/main/res/values-zh/strings.xml
Normal file
25
receivers/android/app/src/main/res/values-zh/strings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<resources>
|
||||
<string name="app_name">FCast接收器</string>
|
||||
<string name="general_failure">操作以一般方式失败</string>
|
||||
<string name="aborted">操作失败,因为它被主动中止</string>
|
||||
<string name="blocked">操作失败,因为被阻止</string>
|
||||
<string name="conflict">操作失败,因为它与设备上已安装的另一个软件包冲突(或不一致)</string>
|
||||
<string name="incompatible">操作失败,因为它与该设备根本不兼容</string>
|
||||
<string name="invalid">操作失败,因为一个或多个 APK 无效</string>
|
||||
<string name="not_enough_storage">由于存储问题,操作失败</string>
|
||||
<string name="downloading_update">正在下载更新…</string>
|
||||
<string name="installing_update">正在安装更新…</string>
|
||||
<string name="success">成功</string>
|
||||
<string name="failed_to_update_with_error">更新包失败并出现错误</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">FCast 接收器有可用的更新,您是否要更新?</string>
|
||||
<string name="never">绝不</string>
|
||||
<string name="close">关闭</string>
|
||||
<string name="update">更新</string>
|
||||
<string name="checking_for_updates">正在检查更新…</string>
|
||||
<string name="no_updates_available">没有可用更新</string>
|
||||
<string name="permission_dialog_title">系统警报窗口权限</string>
|
||||
<string name="permission_dialog_message">此应用需要“系统警报窗口”权限才能在其他应用上方显示内容。请授予此权限。</string>
|
||||
<string name="permission_dialog_positive_button">允许</string>
|
||||
<string name="permission_dialog_negative_button">取消</string>
|
||||
<string name="waiting_for_media">等待媒体</string>
|
||||
</resources>
|
|
@ -7,15 +7,15 @@
|
|||
<string name="incompatible">The operation failed because it is fundamentally incompatible with this device</string>
|
||||
<string name="invalid">The operation failed because one or more of the APKs was invalid</string>
|
||||
<string name="not_enough_storage">The operation failed because of storage issues</string>
|
||||
<string name="downloading_update">Downloading update...</string>
|
||||
<string name="installing_update">Installing update...</string>
|
||||
<string name="downloading_update">Downloading update…</string>
|
||||
<string name="installing_update">Installing update…</string>
|
||||
<string name="success">Success</string>
|
||||
<string name="failed_to_update_with_error">Failed to update package with error</string>
|
||||
<string name="there_is_an_update_available_do_you_wish_to_update">There is an update available for FCast receiver, do you wish to update?</string>
|
||||
<string name="never">Never</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="update">Update</string>
|
||||
<string name="checking_for_updates">Checking for updates...</string>
|
||||
<string name="checking_for_updates">Checking for updates…</string>
|
||||
<string name="no_updates_available">No updates available</string>
|
||||
<string name="permission_dialog_title">System Alert Window Permission</string>
|
||||
<string name="permission_dialog_message">This app requires the System Alert Window permission to display content on top of other apps. Please grant the permission.</string>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '8.2.0' apply false
|
||||
id 'com.android.library' version '8.2.0' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
|
||||
id 'com.android.application' version '8.11.0' apply false
|
||||
id 'com.android.library' version '8.11.0' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '2.2.0' apply false
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#!/bin/sh
|
||||
if [ -z "$ANDROID_VERSION_NAME" ] || [ -z "$ANDROID_VERSION_CODE" ]; then echo "Version name or code not specified. Skipping build."; exit 0; fi
|
||||
|
||||
DOCUMENT_ROOT=/var/www/html
|
||||
|
||||
# Build content
|
||||
echo "Building content..."
|
||||
./gradlew --stacktrace assembleRelease -PversionName=$ANDROID_VERSION_NAME -PversionCode=$ANDROID_VERSION_CODE
|
||||
./gradlew --stacktrace bundlePlaystoreRelease -PversionName=$ANDROID_VERSION_NAME -PversionCode=$ANDROID_VERSION_CODE
|
||||
|
||||
# Take site offline
|
||||
echo "Taking site offline..."
|
||||
touch $DOCUMENT_ROOT/maintenance.file
|
||||
|
||||
# Swap over the content
|
||||
echo "Deploying content..."
|
||||
echo $ANDROID_VERSION_CODE > /var/www/html/fcast-version.txt
|
||||
cp ./app/build/outputs/apk/defaultFlavor/release/app-defaultFlavor-release.apk /var/www/html/fcast-release.apk
|
||||
cp ./app/build/outputs/bundle/playstoreRelease/app-playstore-release.aab /var/www/html/fcast-playstore-release.aab
|
||||
|
||||
# Notify Cloudflare to wipe the CDN cache
|
||||
echo "Purging Cloudflare cache..."
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/zones/ff904f7348b9513064b23e852e328abb/purge_cache" \
|
||||
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"purge_everything":true}'
|
||||
|
||||
sleep 30
|
||||
|
||||
# Take site back online
|
||||
echo "Bringing site back online..."
|
||||
rm $DOCUMENT_ROOT/maintenance.file
|
|
@ -1,6 +1,6 @@
|
|||
#Mon May 01 06:24:43 CDT 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue