mirror of
https://github.com/purplecabbage/phonegap-plugins.git
synced 2026-01-14 08:57:53 -05:00
251 lines
7.1 KiB
Java
251 lines
7.1 KiB
Java
package com.phonegap.plugin.remotesound;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URL;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.Set;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
|
|
import org.apache.cordova.api.Plugin;
|
|
import org.apache.cordova.api.PluginResult;
|
|
import org.apache.cordova.api.PluginResult.Status;
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
import android.content.Context;
|
|
import android.media.MediaPlayer;
|
|
import android.media.MediaPlayer.OnCompletionListener;
|
|
import android.media.MediaPlayer.OnPreparedListener;
|
|
|
|
/**
|
|
* The Class RemoteSoundPlugin allows to perform 2 separate actions: 1- play a
|
|
* remote sound given a URL 2- load and cache sounds given some URLs
|
|
*
|
|
* A usage where load/cache sounds is valuable is when lots of sounds, possibly
|
|
* large, needs to be pre-loaded Play sound is first checking that no other
|
|
* sound with the same name has been cached. If not, it remotely downloads it
|
|
* and cache it on the file system
|
|
*/
|
|
public class RemoteSoundPlugin extends Plugin implements OnPreparedListener, OnCompletionListener {
|
|
|
|
private MediaPlayer mp = null;
|
|
private static final int BUFFER_SIZE = 1024 * 2;
|
|
|
|
@Override
|
|
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
|
PluginResult result = null;
|
|
|
|
if (action.equals("playRemoteSound")) {
|
|
|
|
JSONObject obj = null;
|
|
try {
|
|
obj = args.getJSONObject(0);
|
|
String soundURL = obj.has("soundURL") ? obj.getString("soundURL") : null;
|
|
|
|
if (soundURL != null) {
|
|
this.playSound(soundURL);
|
|
}
|
|
} catch (JSONException jsonEx) {
|
|
|
|
result = new PluginResult(Status.JSON_EXCEPTION);
|
|
}
|
|
}
|
|
|
|
if (action.equals("loadRemoteSounds")) {
|
|
|
|
JSONArray resourceNames = null;
|
|
JSONObject obj = null;
|
|
|
|
try {
|
|
obj = args.getJSONObject(0);
|
|
resourceNames = obj.has("soundURLs") ? obj.getJSONArray("soundURLs") : null;
|
|
|
|
if (resourceNames != null && resourceNames.length() > 0) {
|
|
Set<URL> resources = new HashSet<URL>(resourceNames.length());
|
|
for (int nbElem = 0; nbElem < resourceNames.length(); nbElem++) {
|
|
try {
|
|
resources.add(new URL(resourceNames.getString(nbElem)));
|
|
} catch (MalformedURLException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
if (!resources.isEmpty()) {
|
|
downloadResources(ctx.getContext(), resources);
|
|
}
|
|
}
|
|
|
|
} catch (JSONException jsonEx) {
|
|
|
|
result = new PluginResult(Status.JSON_EXCEPTION);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see
|
|
* android.media.MediaPlayer.OnPreparedListener#onPrepared(android.media
|
|
* .MediaPlayer)
|
|
*/
|
|
public void onPrepared(MediaPlayer mediaplayer) {
|
|
if (mp != null) {
|
|
mp.start();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see
|
|
* android.media.MediaPlayer.OnCompletionListener#onCompletion(android.media
|
|
* .MediaPlayer)
|
|
*/
|
|
public void onCompletion(MediaPlayer mediaplayer) {
|
|
Timer endSound = new Timer();
|
|
endSound.schedule(new TimerTask() {
|
|
public void run() {
|
|
if (mp != null) {
|
|
mp.stop();
|
|
mp.release();
|
|
mp = null;
|
|
}
|
|
}
|
|
}, 200);
|
|
|
|
}
|
|
|
|
/**
|
|
* Play sound, either locally (from assets) or remotely via URL.
|
|
*
|
|
* @param soundUri
|
|
* the sound uri
|
|
*/
|
|
private void playSound(String soundUri) {
|
|
|
|
try {
|
|
|
|
mp = new MediaPlayer();
|
|
|
|
mp.setOnPreparedListener(this);
|
|
mp.setOnCompletionListener(this);
|
|
|
|
FileInputStream fis = null;
|
|
String soundName = soundUri.substring(soundUri.lastIndexOf('/') + 1);
|
|
try {
|
|
|
|
fis = ctx.getApplicationContext().openFileInput(soundName);
|
|
} catch (FileNotFoundException fne) {
|
|
|
|
downloadRemoteMedia(ctx.getApplicationContext(), soundUri, soundName);
|
|
fis = ctx.getApplicationContext().openFileInput(soundName);
|
|
}
|
|
|
|
mp.setDataSource(fis.getFD());
|
|
|
|
mp.setVolume(1.0f, 1.0f);
|
|
mp.prepare();
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Download the url stream to a temporary location and then call the
|
|
*
|
|
*
|
|
* @param context
|
|
* the context
|
|
* @param mediaUrl
|
|
* the media url
|
|
* @param mediaFileName
|
|
* the media file name
|
|
* @return the file
|
|
* @throws IOException
|
|
* Signals that an I/O exception has occurred.
|
|
*/
|
|
private void downloadRemoteMedia(Context context, String mediaUrl, String mediaFileName)
|
|
throws IOException {
|
|
// File downloadingMediaFile = null;
|
|
HttpURLConnection cn = null;
|
|
FileOutputStream out = null;
|
|
InputStream stream = null;
|
|
|
|
try {
|
|
cn = (HttpURLConnection) new URL(mediaUrl).openConnection();
|
|
stream = new BufferedInputStream(cn.getInputStream(), BUFFER_SIZE);
|
|
|
|
// PRIVATE STORAGE. Automatically replace existing files
|
|
out = context.openFileOutput(mediaFileName, Context.MODE_PRIVATE);
|
|
|
|
byte buf[] = new byte[BUFFER_SIZE];
|
|
int len1 = 0;
|
|
|
|
while ((len1 = stream.read(buf)) > 0) {
|
|
out.write(buf, 0, len1);
|
|
}
|
|
|
|
out.close();
|
|
stream.close();
|
|
} finally {
|
|
if (cn != null) {
|
|
cn.disconnect();
|
|
}
|
|
try {
|
|
out.close();
|
|
} catch (IOException e) {
|
|
|
|
}
|
|
try {
|
|
stream.close();
|
|
} catch (IOException e) {
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Download given resources.
|
|
*
|
|
* @param context
|
|
* the context
|
|
* @param resources
|
|
* the resources
|
|
* @return the number of loaded resources
|
|
*/
|
|
private Integer downloadResources(Context context, Set<URL> resources) {
|
|
int nbLoaded = 0;
|
|
|
|
for (Iterator<URL> iterator = resources.iterator(); iterator.hasNext();) {
|
|
|
|
URL url = iterator.next();
|
|
try {
|
|
downloadRemoteMedia(context, url.toString(),
|
|
url.getPath().substring(url.getPath().lastIndexOf('/') + 1));
|
|
nbLoaded++;
|
|
} catch (IOException ioex) {
|
|
ioex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
return nbLoaded;
|
|
}
|
|
|
|
}
|