
Audio-Sharing Plattform, gegründet 2007. Ca. 7 Mio User, web + API + native clients
record / share / stream
Android hat über 5 verschiedene Audio-APIs, mit unterschiedlicher Unterstützung in den Geräten
Neue Geräte
Implementierungsdetails ändern sich sehr schnell
sehr schwer allen Benutzern eine konsistente Experience zu bieten
Ausgabe von “rohen” Audio-Daten (PCM)
AudioTrack track = new AudioTrack(
AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize, AudioTrack.MODE_STREAM);
track.play();
track.write(new byte[] { 1b, 2b, 3b }, 0, 3);
High-level Audio/Video player, unterstützt HTTP Streaming.
MediaPlayer player = new MediaPlayer();
player.setDataSource("http://foo.com/audio.mp3");
player.prepare();
player.start();
Die eigentliche Funktionalität wird von mehreren nativen Frameworks bereitgestellt
Gegenstück zum Player, Aufnahme über das Mikrofon / line-in.
Unterstützte Formate varieren stark mit der Plattform. Gute Qualität (AAC) erst ab Android 2.3.3 möglich.
Im Vergleich zu iOS keine Hardware-Unterstützung für en / decoding!
Low-latency, concurrent playback
Wird normalerweise für Soundeffekte bei Spielen eingesetzt
Ermittlung des Frameworks + spezifischer Code notwendig
manche 2.3+ Geräte benutzen immer noch OpenCORE (v.a. Samsung) - Erkennung nicht immer 100% zuverlässig
if (android.os.BUILD.SDK_INT > 8) {
// enable seeking
}
All non-trivial abstractions, to some degree, are leaky.
The Law of Leaky Abstractions (Joel Spolsky)
namespace android {
enum {
MEDIA_ERROR_BASE = -1000,
ERROR_ALREADY_CONNECTED = MEDIA_ERROR_BASE,
ERROR_NOT_CONNECTED = MEDIA_ERROR_BASE - 1,
ERROR_UNKNOWN_HOST = MEDIA_ERROR_BASE - 2,
ERROR_CANNOT_CONNECT = MEDIA_ERROR_BASE - 3,
ERROR_IO = MEDIA_ERROR_BASE - 4,
// ...
}
}
Das bedeutet:
→ Aufwand vs. Kontrolle
OpenSL ES is an application-level C-language audio API designed for resource-constrained devices.
Seit Android 2.3 - zugänglich mit dem Android NDK (C/C++).
Vermeidet den overhead von JNI, löst jedoch nicht das Latenzproblem.
Wichtig für realtime-Andwendungen, z.B. virtuelle Synthesizer.
Idealerweise < 10ms
Störfaktoren: CPU time, GC-Zyklen, JNI, I/O
Audiocode leicht portierbar, z.Zt. nur ARMv7 (FPU), später auch x86
Dank JNI problemloses Mischen von nativem und Java-Code möglich
Android Service zwingend erforderlich
public class MyPlaybackService extends Service {
public void onCreate() {
startForeground(SERVICE_ID, getNotification());
}
}
Mit WifiLocks, PowerLocks, ...
Lifecycle: MediaPlayer.release(), AudioTrack.stop()
"Ongoing notification" für den aktuellen Track
(Spotify)
Albumartwork in Notifications
(UberMusic)
AudioManager m = getAudioManager();
m.registerMediaButtonEventReceiver(
new ComponentName(getPackageName(),
RemoteControl.class.getName()));
Receiver:
public class RemoteControl extends BroadcastReceiver {
public void onReceive(Context c, Intent i) {
//
}
}
ACTION_AUDIO_BECOMING_NOISY
// Android 2.2+
public void play() {
AudioManager m = getAudioManager();
m.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
}
public void onAudioFocusChange(int change) {
// play track if focus obtained
}
Wichtig wenn mehrere apps gleichzeitig laufen
TelephonyManager tmgr =
getTelephonyManager();
tmgr.listen(this,
PhoneStateListener.LISTEN_CALL_STATE);
public void onCallStateChanged(int state,
String incomingNumber) {
//
}
Verarbeitung:
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<data android:mimeType="audio/*"/>
</intent-filter>
Erstellung:
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT"/>
<data android:mimeType="audio/*"/>
</intent-filter>
TapeMachine
TapeMachine: Share
<audio controls>
<source src="scotty.mp3" type="audio/mp3">
<source src="scotty.ogg" type="audio/ogg">
Your browser does not support the audio element.
</audio>