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:
@@ -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>
|
||||
Reference in New Issue
Block a user