[Feature] Use FTP server URL as notification content text.

Fixes: #792
This commit is contained in:
Hai Zhang 2023-08-09 00:53:27 -07:00
parent 65456a326d
commit 94fc0374bf
33 changed files with 143 additions and 105 deletions

View File

@ -6,7 +6,10 @@
package me.zhanghai.android.files.compat
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.util.AttributeSet
@ -38,6 +41,12 @@ fun Context.getColorStateListCompat(@ColorRes id: Int): ColorStateList =
fun Context.getDrawableCompat(@DrawableRes id: Int): Drawable =
AppCompatResources.getDrawable(this, id)!!
fun <T> Context.getSystemServiceCompat(serviceClass: Class<T>): T =
ContextCompat.getSystemService(this, serviceClass)!!
val Context.mainExecutorCompat: Executor
get() = ContextCompat.getMainExecutor(this)
@SuppressLint("RestrictedApi")
fun Context.obtainStyledAttributesCompat(
set: AttributeSet? = null,
@ -60,11 +69,11 @@ inline fun <R> TintTypedArray.use(block: (TintTypedArray) -> R): R {
}
}
val Context.mainExecutorCompat: Executor
get() = ContextCompat.getMainExecutor(this)
fun <T> Context.getSystemServiceCompat(serviceClass: Class<T>): T =
ContextCompat.getSystemService(this, serviceClass)!!
fun Context.registerReceiverCompat(
receiver: BroadcastReceiver?,
filter: IntentFilter,
flags: Int
): Intent? = ContextCompat.registerReceiver(this, receiver, filter, flags)
@RestrictedHiddenApi
private val getThemeResIdMethod by lazyReflectedMethod(Context::class.java, "getThemeResId")

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 2023 Hai Zhang <dreaming.in.code.zh@gmail.com>
* All Rights Reserved.
*/
package me.zhanghai.android.files.compat
import android.app.Service
import androidx.core.app.ServiceCompat
fun Service.stopForegroundCompat(flags: Int) {
ServiceCompat.stopForeground(this, flags)
}

View File

@ -10,8 +10,10 @@ import android.app.Service
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.ServiceCompat
import me.zhanghai.android.files.R
import me.zhanghai.android.files.app.NotificationIds
import me.zhanghai.android.files.compat.stopForegroundCompat
import me.zhanghai.android.files.util.NotificationChannelTemplate
import me.zhanghai.android.files.util.NotificationTemplate
import me.zhanghai.android.files.util.createIntent
@ -28,14 +30,22 @@ val ftpServerServiceNotificationTemplate: NotificationTemplate =
colorRes = R.color.color_primary,
smallIcon = R.drawable.notification_icon,
contentTitleRes = R.string.ftp_server_notification_title,
contentTextRes = R.string.ftp_server_notification_text,
ongoing = true,
category = NotificationCompat.CATEGORY_SERVICE,
priority = NotificationCompat.PRIORITY_LOW
)
object FtpServerServiceNotification {
fun startForeground(service: Service) {
class FtpServerNotification(private val service: Service) {
private val receiver = FtpServerUrl.createChangeReceiver(service) { doStartForeground() }
fun startForeground() {
doStartForeground()
receiver.register()
}
private fun doStartForeground() {
val contextText = FtpServerUrl.getUrl()
?: service.getString(R.string.ftp_server_notification_text_no_local_inet_address)
val contentIntent = FtpServerActivity::class.createIntent()
var pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@ -49,16 +59,17 @@ object FtpServerServiceNotification {
service, FtpServerReceiver::class.hashCode(), stopIntent, pendingIntentFlags
)
val notification = ftpServerServiceNotificationTemplate.createBuilder(service)
.setContentText(contextText)
.setContentIntent(contentPendingIntent)
.addAction(
R.drawable.stop_icon_white_24dp, service.getString(R.string.stop),
stopPendingIntent
R.drawable.stop_icon_white_24dp, service.getString(R.string.stop), stopPendingIntent
)
.build()
service.startForeground(NotificationIds.FTP_SERVER, notification)
}
fun stopForeground(service: Service) {
service.stopForeground(true)
fun stopForeground() {
receiver.unregister()
service.stopForegroundCompat(ServiceCompat.STOP_FOREGROUND_REMOVE)
}
}

View File

@ -28,6 +28,8 @@ class FtpServerService : Service() {
private lateinit var wakeLock: FtpServerWakeLock
private lateinit var notification: FtpServerNotification
private val executorService = Executors.newSingleThreadExecutor()
private var server: FtpServer? = null
@ -36,6 +38,7 @@ class FtpServerService : Service() {
super.onCreate()
wakeLock = FtpServerWakeLock()
notification = FtpServerNotification(this)
executeStart()
}
@ -55,7 +58,7 @@ class FtpServerService : Service() {
return
}
wakeLock.acquire()
FtpServerServiceNotification.startForeground(this)
notification.startForeground()
state = State.STARTING
executorService.execute { doStart() }
}
@ -63,7 +66,7 @@ class FtpServerService : Service() {
private fun onStartError(exception: Exception) {
state = State.STOPPED
showToast(exception.toString())
FtpServerServiceNotification.stopForeground(this)
notification.stopForeground()
wakeLock.release()
stopSelf()
}
@ -74,7 +77,7 @@ class FtpServerService : Service() {
}
state = State.STOPPING
executorService.execute { doStop() }
FtpServerServiceNotification.stopForeground(this)
notification.stopForeground()
wakeLock.release()
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023 Hai Zhang <dreaming.in.code.zh@gmail.com>
* All Rights Reserved.
*/
package me.zhanghai.android.files.ftpserver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import me.zhanghai.android.files.settings.Settings
import me.zhanghai.android.files.util.RuntimeBroadcastReceiver
import me.zhanghai.android.files.util.getLocalAddress
import me.zhanghai.android.files.util.valueCompat
import java.net.InetAddress
object FtpServerUrl {
fun getUrl(): String? {
val localAddress = InetAddress::class.getLocalAddress() ?: return null
val username = if (!Settings.FTP_SERVER_ANONYMOUS_LOGIN.valueCompat) {
Settings.FTP_SERVER_USERNAME.valueCompat
} else {
null
}
val host = localAddress.hostAddress
val port = Settings.FTP_SERVER_PORT.valueCompat
return "ftp://${if (username != null) "$username@" else ""}$host:$port/"
}
fun createChangeReceiver(context: Context, onChange: () -> Unit): RuntimeBroadcastReceiver =
RuntimeBroadcastReceiver(
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION), object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
onChange()
}
}, context
)
}

View File

@ -5,11 +5,7 @@
package me.zhanghai.android.files.ftpserver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.util.AttributeSet
import android.view.ContextMenu
import android.view.ContextMenu.ContextMenuInfo
@ -25,16 +21,13 @@ import me.zhanghai.android.files.R
import me.zhanghai.android.files.app.clipboardManager
import me.zhanghai.android.files.settings.Settings
import me.zhanghai.android.files.util.copyText
import me.zhanghai.android.files.util.getLocalAddress
import me.zhanghai.android.files.util.valueCompat
import java.net.InetAddress
class FtpServerUrlPreference : Preference {
private val observer = Observer<Any> { updateSummary() }
private val connectivityReceiver = ConnectivityReceiver()
private val observer = Observer<Any> { updateUrl() }
private val receiver = FtpServerUrl.createChangeReceiver(context) { updateUrl() }
private val contextMenuListener = ContextMenuListener()
private var hasUrl = false
private var url: String? = null
constructor(context: Context) : super(context)
@ -53,7 +46,7 @@ class FtpServerUrlPreference : Preference {
init {
isPersistent = false
updateSummary()
updateUrl()
}
override fun onAttached() {
@ -62,9 +55,7 @@ class FtpServerUrlPreference : Preference {
Settings.FTP_SERVER_ANONYMOUS_LOGIN.observeForever(observer)
Settings.FTP_SERVER_USERNAME.observeForever(observer)
Settings.FTP_SERVER_PORT.observeForever(observer)
context.registerReceiver(
connectivityReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
)
receiver.register()
}
override fun onDetached() {
@ -73,76 +64,45 @@ class FtpServerUrlPreference : Preference {
Settings.FTP_SERVER_ANONYMOUS_LOGIN.removeObserver(observer)
Settings.FTP_SERVER_USERNAME.removeObserver(observer)
Settings.FTP_SERVER_PORT.removeObserver(observer)
context.unregisterReceiver(connectivityReceiver)
receiver.unregister()
}
private fun updateSummary() {
val localAddress = InetAddress::class.getLocalAddress()
val summary: String
if (localAddress != null) {
val username = if (!Settings.FTP_SERVER_ANONYMOUS_LOGIN.valueCompat) {
Settings.FTP_SERVER_USERNAME.valueCompat
} else {
null
}
val host = localAddress.hostAddress
val port = Settings.FTP_SERVER_PORT.valueCompat
summary = "ftp://${if (username != null) "$username@" else ""}$host:$port/"
hasUrl = true
} else {
summary = context.getString(R.string.ftp_server_url_summary_no_local_inet_address)
hasUrl = false
}
setSummary(summary)
private fun updateUrl() {
url = FtpServerUrl.getUrl()
summary = url ?: context.getString(R.string.ftp_server_url_summary_no_local_inet_address)
}
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
holder.itemView.setOnCreateContextMenuListener(contextMenuListener)
}
private inner class ConnectivityReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (val action = intent.action) {
ConnectivityManager.CONNECTIVITY_ACTION -> updateSummary()
else -> throw IllegalArgumentException(action)
}
}
}
private inner class ContextMenuListener : OnCreateContextMenuListener {
override fun onCreateContextMenu(
menu: ContextMenu, view: View, menuInfo: ContextMenuInfo?
) {
if (!hasUrl) {
return
}
val url = summary!!
menu
.setHeaderTitle(url)
.apply {
holder.itemView.setOnCreateContextMenuListener(object : OnCreateContextMenuListener {
override fun onCreateContextMenu(
menu: ContextMenu,
view: View,
menuInfo: ContextMenuInfo?
) {
val url = url ?: return
menu.apply {
setHeaderTitle(url)
add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.ftp_server_url_menu_copy_url)
.setOnMenuItemClickListener {
clipboardManager.copyText(url, context)
true
}
}
.apply {
if (!Settings.FTP_SERVER_ANONYMOUS_LOGIN.valueCompat) {
val password = Settings.FTP_SERVER_PASSWORD.valueCompat
if (password.isNotEmpty()) {
add(
Menu.NONE, Menu.NONE, Menu.NONE,
R.string.ftp_server_url_menu_copy_password
)
.setOnMenuItemClickListener {
clipboardManager.copyText(password, context)
true
}
).setOnMenuItemClickListener {
clipboardManager.copyText(password, context)
true
}
}
}
}
}
}
})
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 Hai Zhang <dreaming.in.code.zh@gmail.com>
* All Rights Reserved.
*/
package me.zhanghai.android.files.util
import android.content.BroadcastReceiver
import android.content.Context
import android.content.IntentFilter
import androidx.core.content.ContextCompat
import me.zhanghai.android.files.compat.registerReceiverCompat
class RuntimeBroadcastReceiver(
private val filter: IntentFilter,
private val receiver: BroadcastReceiver,
private val context: Context,
private val flags: Int = ContextCompat.RECEIVER_NOT_EXPORTED
) {
fun register() {
context.registerReceiverCompat(receiver, filter, flags)
}
fun unregister() {
context.unregisterReceiver(receiver)
}
}

View File

@ -674,7 +674,6 @@
<string name="ftp_server_port_title">منفذ</string>
<string name="ftp_server_home_directory_title">المجلد الرئيسي</string>
<string name="ftp_server_writable_title">اسمح بالكتابة</string>
<string name="ftp_server_notification_text">خادم FTP قيد التشغيل</string>
<string name="settings_title">الإعدادات</string>
<string name="settings_interface_title">واجهة المستخدم</string>

View File

@ -468,7 +468,6 @@
<string name="ftp_server_port_title">Порт</string>
<string name="ftp_server_home_directory_title">Основна папка</string>
<string name="ftp_server_writable_title">Разрешаване на писане</string>
<string name="ftp_server_notification_text">FTP сървърът работи</string>
<string name="settings_title">Настройки</string>
<string name="settings_interface_title">Интерфейс</string>

View File

@ -557,7 +557,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Složka Root</string>
<string name="ftp_server_writable_title">Povolit zapisování</string>
<string name="ftp_server_notification_text">FTP server běží</string>
<string name="settings_title">Nastavení</string>
<string name="settings_interface_title">Rozhraní</string>

View File

@ -554,7 +554,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Stammverzeichnis</string>
<string name="ftp_server_writable_title">Erlaube Schreiben</string>
<string name="ftp_server_notification_text">FTP-Server läuft</string>
<string name="settings_title">Einstellungen</string>
<string name="settings_interface_title">Benutzeroberfläche</string>

View File

@ -501,7 +501,6 @@
<string name="ftp_server_port_title">Puerto</string>
<string name="ftp_server_home_directory_title">Carpeta raíz</string>
<string name="ftp_server_writable_title">Permitir escritura</string>
<string name="ftp_server_notification_text">El servidor FTP está corriendo</string>
<string name="settings_title">Ajustes</string>
<string name="settings_interface_title">Interfaz</string>

View File

@ -373,7 +373,6 @@
<string name="ftp_server_port_title">Ataka</string>
<string name="ftp_server_home_directory_title">Erro karpeta</string>
<string name="ftp_server_writable_title">Baimendu idaztea</string>
<string name="ftp_server_notification_text">FTP zerbitzaria abian da</string>
<string name="settings_title">Ezarpenak</string>
<string name="settings_interface_title">Interfazea</string>

View File

@ -505,7 +505,6 @@
<string name="ftp_server_port_title">درگاه</string>
<string name="ftp_server_home_directory_title">شاخهٔ ریشه</string>
<string name="ftp_server_writable_title">اجازهٔ نوشتن</string>
<string name="ftp_server_notification_text">کارساز اف‌تی‌پی در حال اجراست</string>
<string name="settings_title">تنظیمات</string>
<string name="settings_interface_title">رابط</string>

View File

@ -556,7 +556,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Dossier root</string>
<string name="ftp_server_writable_title">Autoriser l\'écriture</string>
<string name="ftp_server_notification_text">Le serveur FTP fonctionne</string>
<string name="settings_title">Réglages</string>
<string name="settings_interface_title">Interface</string>

View File

@ -501,7 +501,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Gyökérmappa</string>
<string name="ftp_server_writable_title">Írás engedélyezése</string>
<string name="ftp_server_notification_text">Az FTP-kiszolgáló fut</string>
<string name="settings_title">Beállítások</string>
<string name="settings_interface_title">Felület</string>

View File

@ -524,7 +524,6 @@
<string name="ftp_server_port_title">Porta</string>
<string name="ftp_server_home_directory_title">Folder root</string>
<string name="ftp_server_writable_title">Izinkan menyimpan</string>
<string name="ftp_server_notification_text">Server FTP sedang berjalan</string>
<string name="settings_title">Pengaturan</string>
<string name="settings_interface_title">Antarmuka</string>

View File

@ -556,7 +556,6 @@
<string name="ftp_server_port_title">Gátt</string>
<string name="ftp_server_home_directory_title">Rótarmappa</string>
<string name="ftp_server_writable_title">Leyfa skrifun</string>
<string name="ftp_server_notification_text">FTP-netþjónn er í gangi</string>
<string name="settings_title">Stillingar</string>
<string name="settings_interface_title">Viðmót</string>

View File

@ -554,7 +554,6 @@
<string name="ftp_server_port_title">Porta</string>
<string name="ftp_server_home_directory_title">Cartella root</string>
<string name="ftp_server_writable_title">Consenti scrittura</string>
<string name="ftp_server_notification_text">Il server FTP è attivo</string>
<string name="settings_title">Impostazioni</string>
<string name="settings_interface_title">Interfaccia</string>

View File

@ -614,7 +614,6 @@
<string name="ftp_server_port_title">פתחה</string>
<string name="ftp_server_home_directory_title">תיקיית שורש</string>
<string name="ftp_server_writable_title">איפשור כתיבה</string>
<string name="ftp_server_notification_text">שרת FTP פועל</string>
<string name="settings_title">הגדרות</string>
<string name="settings_interface_title">ממשק</string>

View File

@ -524,7 +524,6 @@
<string name="ftp_server_port_title">ポート</string>
<string name="ftp_server_home_directory_title">Root フォルダ</string>
<string name="ftp_server_writable_title">書き込みを許可</string>
<string name="ftp_server_notification_text">FTP サーバーを実行中です</string>
<string name="settings_title">設定</string>
<string name="settings_interface_title">外観</string>

View File

@ -524,7 +524,6 @@
<string name="ftp_server_port_title">포트</string>
<string name="ftp_server_home_directory_title">루트 폴더</string>
<string name="ftp_server_writable_title">쓰기 허용</string>
<string name="ftp_server_notification_text">FTP 서버가 실행 중입니다</string>
<string name="settings_title">설정</string>
<string name="settings_interface_title">인터페이스</string>

View File

@ -554,7 +554,6 @@
<string name="ftp_server_port_title">Poort</string>
<string name="ftp_server_home_directory_title">Hoofdmap</string>
<string name="ftp_server_writable_title">Wegschrijven toestaan</string>
<string name="ftp_server_notification_text">De FTP-server draait</string>
<string name="settings_title">Instellingen</string>
<string name="settings_interface_title">Uiterlijk</string>

View File

@ -614,7 +614,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Katalog główny</string>
<string name="ftp_server_writable_title">Zezwól na zapis</string>
<string name="ftp_server_notification_text">Serwer FTP jest uruchomiony</string>
<string name="settings_title">Ustawienia</string>
<string name="settings_interface_title">Interfejs</string>

View File

@ -503,7 +503,6 @@
<string name="ftp_server_port_title">Porta</string>
<string name="ftp_server_home_directory_title">Pasta raiz</string>
<string name="ftp_server_writable_title">Permitir escrita</string>
<string name="ftp_server_notification_text">O servidor FTP está sendo executado</string>
<string name="settings_title">Configurações</string>
<string name="settings_interface_title">Interface</string>

View File

@ -473,7 +473,6 @@
<string name="ftp_server_port_title">Porta</string>
<string name="ftp_server_home_directory_title">Pasta root</string>
<string name="ftp_server_writable_title">Permitir escrita</string>
<string name="ftp_server_notification_text">Servidor FTP em execução</string>
<string name="settings_title">Definições</string>
<string name="settings_interface_title">Interface</string>

View File

@ -584,7 +584,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Dosar rădăcină</string>
<string name="ftp_server_writable_title">Permite scrierea</string>
<string name="ftp_server_notification_text">Serverul FTP funcționează</string>
<string name="settings_title">Setări</string>
<string name="settings_interface_title">Interfață</string>

View File

@ -616,7 +616,6 @@
<string name="ftp_server_port_title">Порт</string>
<string name="ftp_server_home_directory_title">Корневой каталог</string>
<string name="ftp_server_writable_title">Разрешить запись</string>
<string name="ftp_server_notification_text">FTP-сервер запущен</string>
<string name="settings_title">Настройки</string>
<string name="settings_interface_title">Интерфейс</string>

View File

@ -535,7 +535,6 @@
<string name="ftp_server_port_title">Port</string>
<string name="ftp_server_home_directory_title">Kök klasör</string>
<string name="ftp_server_writable_title">Yazmaya izin ver</string>
<string name="ftp_server_notification_text">FTP sunucusu çalışıyor</string>
<string name="settings_title">Ayarlar</string>
<string name="settings_interface_title">Arayüz</string>

View File

@ -524,7 +524,6 @@
<string name="ftp_server_port_title">Cổng</string>
<string name="ftp_server_home_directory_title">Thư mục gốc</string>
<string name="ftp_server_writable_title">Cho phép ghi</string>
<string name="ftp_server_notification_text">Máy chủ FTP đang chạy</string>
<string name="settings_title">Cài đặt</string>
<string name="settings_interface_title">Giao diện</string>

View File

@ -533,7 +533,6 @@
<string name="ftp_server_port_title">端口</string>
<string name="ftp_server_home_directory_title">根文件夹</string>
<string name="ftp_server_writable_title">允许写入</string>
<string name="ftp_server_notification_text">FTP 服务器正在运行</string>
<string name="settings_title">设置</string>
<string name="settings_interface_title">界面</string>

View File

@ -533,7 +533,6 @@
<string name="ftp_server_port_title">連接埠</string>
<string name="ftp_server_home_directory_title">根資料夾</string>
<string name="ftp_server_writable_title">允許寫入</string>
<string name="ftp_server_notification_text">FTP 伺服器正在執行</string>
<string name="settings_title">設定</string>
<string name="settings_interface_title">介面</string>

View File

@ -665,7 +665,7 @@
<string name="ftp_server_home_directory_title">Root folder</string>
<string name="ftp_server_writable_title">Allow writing</string>
<string name="ftp_server_notification_title" translatable="false">@string/ftp_server_title</string>
<string name="ftp_server_notification_text">FTP server is running</string>
<string name="ftp_server_notification_text_no_local_inet_address" translatable="false">@string/ftp_server_url_summary_no_local_inet_address</string>
<string name="settings_title">Settings</string>
<string name="settings_interface_title">Interface</string>