com.pearson.plugins.audio.PearsonAudioHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.pearson.plugins.audio.PearsonAudioHandler.java

Source

/*
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.  The ASF licenses this file
   to you under the Apache License, Version 2.0 (the
   "License"); you may not use this file except in compliance
   with the License.  You may obtain a copy of the License at
    
     http://www.apache.org/licenses/LICENSE-2.0
    
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.
 */
package com.pearson.plugins.audio;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.apache.cordova.file.FileHelper;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import android.annotation.SuppressLint;
import android.content.Context;
import android.media.AudioManager;
import android.net.Uri;

/**
 * This class called by CordovaActivity to play and record audio. The file can
 * be local or over a network using http.
 *
 * Audio formats supported (tested): .mp3, .wav
 *
 * Local audio files must reside in one of two places: android_asset: file name
 * must start with /android_asset/sound.mp3 sdcard: file name is just sound.mp3
 */
public class PearsonAudioHandler extends CordovaPlugin {

    public static String TAG = "PearsonAudioHandler";
    PearsonAudioPlayer player; // Audio player object
    private CallbackContext messageChannel;

    /**
     * Constructor.
     */
    public PearsonAudioHandler() {

    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        prepareAudioManager();
    }

    /**
     * Executes the request and returns PluginResult.
     * 
     * @param action
     *            The action to execute.
     * @param args
     *            JSONArry of arguments for the plugin.
     * @param callbackContext
     *            The callback context used when calling back into JavaScript.
     * @return A PluginResult object with a status and message.
     */
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        CordovaResourceApi resourceApi = webView.getResourceApi();
        PluginResult.Status status = PluginResult.Status.OK;
        String result = "";
        System.out.println("EXECUTED::" + action);
        if (action.equals("startPlayingAudio")) {
            String target = args.getString(1);
            String fileUriStr;
            try {
                Uri targetUri = resourceApi.remapUri(Uri.parse(target));
                fileUriStr = targetUri.toString();
            } catch (IllegalArgumentException e) {
                fileUriStr = target;
            }
            this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr));
        } else if (action.equals("seekToAudio")) {
            this.seekToAudio(args.getString(0), args.getInt(1));
        } else if (action.equals("pausePlayingAudio")) {
            this.pausePlayingAudio(args.getString(0));
        } else if (action.equals("stopPlayingAudio")) {
            this.stopPlayingAudio(args.getString(0));
        } else if (action.equals("setVolume")) {
            try {
                this.setVolume(args.getString(0), Float.parseFloat(args.getString(1)));
            } catch (NumberFormatException nfe) {
                // no-op
            }
        } else if (action.equals("getCurrentPositionAudio")) {
            float f = this.getCurrentPositionAudio(args.getString(0));
            callbackContext.sendPluginResult(new PluginResult(status, f));
            return true;
        } else if (action.equals("getDurationAudio")) {
            float f = this.getDurationAudio();
            callbackContext.sendPluginResult(new PluginResult(status, f));
            return true;
        } else if (action.equals("create")) {
            String id = args.getString(0);
            String src = FileHelper.stripFileProtocol(args.getString(1));
            PearsonAudioPlayer audio = new PearsonAudioPlayer(this, id, src);
            // this.player.put(id, audio);
            System.out.println("CREATED");
            this.player = audio;
        } else if (action.equals("release")) {
            boolean b = this.release(args.getString(0));
            callbackContext.sendPluginResult(new PluginResult(status, b));
            return true;
        } else if (action.equals("setPlayBackRate")) {
            this.setPlayBackRate(args.getInt(1));
        } else { // Unrecognized action.
            return false;
        }

        callbackContext.sendPluginResult(new PluginResult(status, result));

        return true;
    }

    private void setPlayBackRate(int rate) {
        if (player != null) {
            player.setPlayBackRate(rate);
        }
    }

    /**
     * Stop all audio players and recorders.
     */
    public void onDestroy() {
        player.destroy();
        player = null; // clear();
    }

    /**
     * Stop all audio players and recorders on navigate.
     */
    @Override
    public void onReset() {
        onDestroy();
    }

    /**
     * Called when a message is sent to plugin.
     *
     * @param id
     *            The message id
     * @param data
     *            The message data
     * @return Object to stop propagation or null
     */
    public Object onMessage(String id, Object data) {

        // If phone message
        if (id.equals("telephone")) {

            // If phone ringing, then pause playing
            if ("ringing".equals(data) || "offhook".equals(data)) {
                if (player.getState() == PearsonAudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
                    player.pausePlaying();
                }
            }

            // If phone idle, then resume playing those players we paused
            else if ("idle".equals(data)) {
                player.startPlaying();
            }
        }
        return null;
    }

    // --------------------------------------------------------------------------
    // LOCAL METHODS
    // --------------------------------------------------------------------------

    /**
     * Release the audio player instance to save memory.
     * 
     * @param id
     *            The id of the audio player
     */
    private boolean release(String id) {
        player.destroy();
        return true;
    }

    /**
     * Start or resume playing audio file.
     * 
     * @param id
     *            The id of the audio player
     * @param file
     *            The name of the audio file.
     */
    public void startPlayingAudio(String id, String file) {
        if (player == null) {
            player = new PearsonAudioPlayer(this, id, file);
        }
        player.startPlaying();
    }

    /**
     * Seek to a location.
     * 
     * @param id
     *            The id of the audio player
     * @param milliseconds
     *            int: number of milliseconds to skip 1000 = 1 second
     */
    public void seekToAudio(String id, int milliseconds) {
        if (player != null) {
            player.seekToPlaying(milliseconds);
        }
    }

    /**
     * Pause playing.
     * 
     * @param id
     *            The id of the audio player
     */
    public void pausePlayingAudio(String id) {
        if (player != null) {
            player.pausePlaying();
        }
    }

    /**
     * Stop playing the audio file.
     * 
     * @param id
     *            The id of the audio player
     */
    public void stopPlayingAudio(String id) {
        if (player != null) {
            player.stopPlaying();
        }
    }

    /**
     * Get current position of playback.
     * 
     * @param id
     *            The id of the audio player
     * @return position in msec
     */
    public int getCurrentPositionAudio(String id) {
        if (player != null) {
            return player.getCurrentPosition();
        }
        return -1;
    }

    /**
     * Get the duration of the audio file.
     * 
     * @param id
     *            The id of the audio player
     * @param file
     *            The name of the audio file.
     * @return The duration in msec.
     */
    public int getDurationAudio() {
        if (player != null) {
            return player.getDuration();
        }
        return -1;
    }

    /**
     * Set the audio device to be used for playback.
     *
     * @param output
     *            1=earpiece, 2=speaker
     */
    @SuppressWarnings("deprecation")
    public void setAudioOutputDevice(int output) {
        AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE);
        if (output == 2) {
            audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
        } else if (output == 1) {
            audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
        } else {
            System.out.println("AudioHandler.setAudioOutputDevice() Error: Unknown output device.");
        }
    }

    /*package*/ Integer samplerate = 44100;
    /*package*/ Integer buffersize = 512;

    @SuppressLint("NewApi")
    private void prepareAudioManager() {
        // Get the device's sample rate and buffer size to enable low-latency
        // Android audio output, if available.
        AudioManager audioManager = (AudioManager) this.cordova.getActivity()
                .getSystemService(Context.AUDIO_SERVICE);
        try {
            samplerate = Integer.parseInt(audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
        } catch (NoSuchMethodError ignored) {
        } catch (NumberFormatException ignored) {
        }
        try {
            buffersize = Integer.parseInt(audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
        } catch (NoSuchMethodError ignored) {
        } catch (NumberFormatException ignored) {
        }
    }

    /**
     * Get the audio device to be used for playback.
     *
     * @return 1=earpiece, 2=speaker
     */
    @SuppressWarnings("deprecation")
    public int getAudioOutputDevice() {
        AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE);
        if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) {
            return 1;
        }
        if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_SPEAKER) {
            return 2;
        }
        return -1;
    }

    /**
     * Set the volume for an audio device
     *
     * @param id
     *            The id of the audio player
     * @param volume
     *            Volume to adjust to 0.0f - 1.0f
     */
    public void setVolume(String id, float volume) {
        AudioManager audioManager = (AudioManager) this.cordova.getActivity()
                .getSystemService(Context.AUDIO_SERVICE);
        int max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        // Why sqrt? just to make smoother audio rise up 
        System.out.println("VOLUMERATE::" + volume);
        System.out.println("MAX::" + max);
        System.out.println("FINALVOLUME::" + Math.round(volume * max));
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, Math.round(volume * max), 0);
    }

    void sendEventMessage(String action, JSONObject actionData) {
        JSONObject message = new JSONObject();
        try {
            message.put("action", action);
            if (actionData != null) {
                message.put(action, actionData);
            }
        } catch (JSONException e) {
            Log.e(TAG, "Failed to create event message", e);
        }

        PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, message);
        pluginResult.setKeepCallback(true);
        if (messageChannel != null) {
            messageChannel.sendPluginResult(pluginResult);
        }
    }
}