Skip to content

Commit

Permalink
refactor AudioplayerPlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
ralph-bergmann committed Feb 22, 2018
1 parent 48a4c1f commit cb74c2a
Showing 1 changed file with 146 additions and 96 deletions.
242 changes: 146 additions & 96 deletions android/src/main/java/bz/rxla/audioplayer/AudioplayerPlugin.java
@@ -1,152 +1,202 @@
package bz.rxla.audioplayer;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.util.Log;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.PluginRegistry.Registrar;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/**
* AudioplayerPlugin
*/
public class AudioplayerPlugin implements MethodCallHandler {
private final MethodChannel channel;
private Activity activity;
public class AudioplayerPlugin implements MethodCallHandler, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {

final Handler handler = new Handler();
private final MethodChannel channel;
private final Map<String, MediaPlayer> mediaPlayers = new HashMap<>();
private final Handler handler = new Handler();
private Runnable positionUpdates;

Map<String, MediaPlayer> mediaPlayers = new HashMap<>();

public static void registerWith(Registrar registrar) {
public static void registerWith(final Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "bz.rxla.flutter/audio");
channel.setMethodCallHandler(new AudioplayerPlugin(registrar.activity(), channel));
channel.setMethodCallHandler(new AudioplayerPlugin(channel));
}

private AudioplayerPlugin(Activity activity, MethodChannel channel) {
this.activity = activity;
private AudioplayerPlugin(final MethodChannel channel) {
this.channel = channel;
this.channel.setMethodCallHandler(this);
}

@Override
public void onMethodCall(MethodCall call, MethodChannel.Result response) {
String playerId = ((HashMap) call.arguments()).get("playerId").toString();
if (call.method.equals("play")) {
String url = ((HashMap) call.arguments()).get("url").toString();
double volume = (double)((HashMap) call.arguments()).get("volume");
Boolean resPlay = play(playerId, url, (float)volume);
response.success(1);
} else if (call.method.equals("pause")) {
pause(playerId);
response.success(1);
} else if (call.method.equals("stop")) {
stop(playerId);
response.success(1);
} else if (call.method.equals("seek")) {
double position = Double.parseDouble(((HashMap) call.arguments()).get("position").toString());
seek(playerId, position);
response.success(1);
} else {
response.notImplemented();
public void onMethodCall(final MethodCall call, final MethodChannel.Result response) {
final String playerId = call.argument("playerId");
switch (call.method) {
case "play":
final String url = call.argument("url");
final double volume = call.argument("volume");
try {
play(playerId, url, (float) volume);
response.success(1);
} catch (IOException e) {
e.printStackTrace();
response.error("IOException", e.getMessage(), e);
}
break;
case "pause":
pause(playerId);
response.success(1);
break;
case "stop":
stop(playerId);
response.success(1);
break;
case "seek":
double position = call.argument("position");
seek(playerId, position);
response.success(1);
break;
default:
response.notImplemented();
break;
}
}

private void seek(String playerId, double position) {
@Override
public void onPrepared(final MediaPlayer mediaPlayer) {
mediaPlayer.start();
sendPositionUpdates();
}

@Override
public void onCompletion(final MediaPlayer mediaPlayer) {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
removePlayer(mediaPlayer);
}

private void play(final String playerId, final String url, final float volume) throws IOException {
MediaPlayer mediaPlayer = mediaPlayers.get(playerId);
mediaPlayer.seekTo((int) (position * 1000));
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayers.put(playerId, mediaPlayer);
}
mediaPlayer.setDataSource(url);
mediaPlayer.setVolume(volume, volume);
mediaPlayer.prepareAsync();
}

private void stop(String playerId) {
handler.removeCallbacks(sendData);
private void pause(final String playerId) {
MediaPlayer mediaPlayer = mediaPlayers.get(playerId);
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayers.remove(playerId);
mediaPlayer.pause();
}
}

private void pause(String playerId) {
private void seek(final String playerId, final double position) {
MediaPlayer mediaPlayer = mediaPlayers.get(playerId);
if (mediaPlayer != null) {
mediaPlayer.pause();
mediaPlayer.seekTo((int) (position * 1000));
}
handler.removeCallbacks(sendData);
}

private Boolean play(final String playerId, String url, float volume) {
private void stop(final String playerId) {
MediaPlayer mediaPlayer = mediaPlayers.get(playerId);
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayers.put(playerId, mediaPlayer);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
if (mediaPlayer != null) {
onCompletion(mediaPlayer);
}
}

try {
mediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
Log.d("AUDIO", "invalid DataSource");
private void removePlayer(final MediaPlayer mediaPlayer) {
final Iterator<Map.Entry<String, MediaPlayer>> iterator = mediaPlayers.entrySet().iterator();
while (iterator.hasNext()) {
final Map.Entry<String, MediaPlayer> next = iterator.next();
if (next.getValue() == mediaPlayer) {
iterator.remove();
channel.invokeMethod("audio.onComplete", buildArguments(next.getKey(), true));
break;
}
}
}

try {
mediaPlayer.prepare();
} catch (IOException e) {
Log.d("AUDIO", "media prepare ERROR");
e.printStackTrace();
}
private void sendPositionUpdates() {
if (positionUpdates != null) {
return;
}
positionUpdates = new UpdateCallback(mediaPlayers, channel, handler, this);
handler.post(positionUpdates);
}

channel.invokeMethod("audio.onDuration", buildArguments(playerId, mediaPlayer.getDuration()));
void stopPositionUpdates() {
positionUpdates = null;
handler.removeCallbacksAndMessages(null);
}

mediaPlayer.setVolume(volume, volume);
mediaPlayer.start();
static Map<String, Object> buildArguments(String playerId, Object value) {
Map<String, Object> result = new HashMap<>();
result.put("playerId", playerId);
result.put("value", value);
return result;
}

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stop(playerId);
channel.invokeMethod("audio.onComplete", buildArguments(playerId, true));
}
});
private static final class UpdateCallback implements Runnable {

private final WeakReference<Map<String, MediaPlayer>> _mediaPlayers;
private final WeakReference<MethodChannel> _channel;
private final WeakReference<Handler> _handler;
private final WeakReference<AudioplayerPlugin> _audioplayerPlugin;

UpdateCallback(final Map<String, MediaPlayer> mediaPlayers,
final MethodChannel channel,
final Handler handler,
final AudioplayerPlugin audioplayerPlugin) {
_mediaPlayers = new WeakReference<>(mediaPlayers);
_channel = new WeakReference<>(channel);
_handler = new WeakReference<>(handler);
_audioplayerPlugin = new WeakReference<>(audioplayerPlugin);
}

@Override
public void run() {

handler.post(sendData);
final Map<String, MediaPlayer> mediaPlayers = _mediaPlayers.get();
final MethodChannel channel = _channel.get();
final Handler handler = _handler.get();
final AudioplayerPlugin audioplayerPlugin = _audioplayerPlugin.get();

return true;
}
if (mediaPlayers == null || channel == null || handler == null || audioplayerPlugin == null) {
return;
}

private final Runnable sendData = new Runnable() {
public void run() {
try {
for (String playerId : mediaPlayers.keySet()) {
MediaPlayer mediaPlayer = mediaPlayers.get(playerId);
if (!mediaPlayer.isPlaying()) {
handler.removeCallbacks(sendData);
}
int time = mediaPlayer.getCurrentPosition();
channel.invokeMethod("audio.onCurrentPosition", buildArguments(playerId, time));

handler.postDelayed(this, 200);
if (mediaPlayers.isEmpty()) {
audioplayerPlugin.stopPositionUpdates();
return;
}

for (final Map.Entry<String, MediaPlayer> next : mediaPlayers.entrySet()) {
final MediaPlayer mediaPlayer = next.getValue();
if (!mediaPlayer.isPlaying()) {
continue;
}
} catch (Exception e) {
e.printStackTrace();
final String key = next.getKey();
final int duration = mediaPlayer.getDuration();
final int time = mediaPlayer.getCurrentPosition();
channel.invokeMethod("audio.onDuration", buildArguments(key, duration));
channel.invokeMethod("audio.onCurrentPosition", buildArguments(key, time));
}
handler.postDelayed(this, 200);
}
};

private static Map<String, Object> buildArguments(String playerId, Object value) {
Map<String, Object> result = new HashMap<>();
result.put("playerId", playerId);
result.put("value", value);
return result;
}
}

0 comments on commit cb74c2a

Please sign in to comment.