Cover-Farbe, Teilen aus YouTube, Android Auto, geschärfte Typografie

P3-Liste aus dem UX-Review: Player nimmt Cover-Farbe auf, "Teilen" aus
YouTube trägt die Adresse in den Downloader ein, Android Auto blättert
durch die Bibliothek, Laufweite der Typografie geschärft, Überschriften
vereinheitlicht. 533 Tests grün, flutter analyze ohne Befund.
This commit is contained in:
Hermes (Server)
2026-08-25 09:09:27 +02:00
parent 490e73ce41
commit 60c57577a3
22 changed files with 1040 additions and 40 deletions
+13
View File
@@ -48,12 +48,25 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- "Teilen -> Melo" aus der YouTube-App. Vorher musste man die
Adresse von Hand kopieren und einfuegen. -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- Android Auto: ohne diesen Eintrag taucht Melo dort nicht auf,
auch wenn der MediaBrowserService unten angemeldet ist. Die
Inhalte liefert MeloAudioHandler.getChildren. -->
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
<service
android:name="com.ryanheise.audioservice.AudioService"
android:foregroundServiceType="mediaPlayback"
@@ -0,0 +1,47 @@
package de.baka.melo
import android.content.Intent
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
/**
* Reicht Text weiter, den eine andere App ueber "Teilen" an Melo schickt —
* in der Regel eine YouTube-Adresse.
*
* Eigene Bruecke statt eines Zusatzpakets: das Projekt hat fuer MediaStore
* und Klangeffekte bereits eigene (siehe MediaStoreBridge).
*/
class GeteiltBridge {
companion object {
const val CHANNEL = "de.baka.melo/geteilt"
}
private var offen: String? = null
/**
* Merkt sich den Text eines SEND-Intents. Wird sowohl beim Start als
* auch bei onNewIntent aufgerufen: die Activity laeuft mit singleTop,
* ein zweites Teilen startet sie also nicht neu.
*/
fun nimm(intent: Intent?) {
if (intent?.action != Intent.ACTION_SEND) return
if (intent.type != "text/plain") return
offen = intent.getStringExtra(Intent.EXTRA_TEXT)
// Aus dem Intent entfernen, damit ein Lagewechsel (Drehen) ihn nicht
// ein zweites Mal liefert.
intent.removeExtra(Intent.EXTRA_TEXT)
}
fun handle(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"hole" -> {
// Nach dem Abholen leeren: sonst spraenge die App bei jedem
// Wiedereintritt erneut in den Downloader.
val text = offen
offen = null
result.success(text)
}
else -> result.notImplemented()
}
}
}
@@ -1,11 +1,13 @@
package de.baka.melo
import android.content.Intent
import com.ryanheise.audioservice.AudioServiceActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity : AudioServiceActivity() {
private var audioEffects: AudioEffectsBridge? = null
private val geteilt = GeteiltBridge()
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
@@ -21,6 +23,24 @@ class MainActivity : AudioServiceActivity() {
flutterEngine.dartExecutor.binaryMessenger,
MediaStoreBridge.CHANNEL
).setMethodCallHandler(mediaStore::handle)
// Den Intent, mit dem die App gestartet wurde, gleich mitnehmen —
// Dart fragt kurz danach danach.
geteilt.nimm(intent)
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
GeteiltBridge.CHANNEL
).setMethodCallHandler(geteilt::handle)
}
/**
* Die Activity laeuft mit singleTop: ein zweites Teilen startet sie
* nicht neu, sondern liefert hier einen neuen Intent.
*/
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
geteilt.nimm(intent)
}
override fun onDestroy() {
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Meldet Melo bei Android Auto als Musik-App an. Ohne diese Datei taucht die
App dort gar nicht erst auf — der MediaBrowserService allein reicht nicht.
-->
<automotiveApp>
<uses name="media"/>
</automotiveApp>