Skip to content

Commit

Permalink
Merge PR apache#137 for android playAudioWhenScreenIsLocked
Browse files Browse the repository at this point in the history
  • Loading branch information
Buddy Reno committed Nov 10, 2017
1 parent 5cf51e5 commit b55295c
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 53 deletions.
145 changes: 107 additions & 38 deletions src/android/AudioHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,27 @@ Licensed to the Apache Software Foundation (ASF) under one
*/
package org.apache.cordova.media;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.PermissionHelper;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.net.Uri;
import android.os.Build;

import java.security.Permission;

import java.util.ArrayList;
import java.util.HashMap;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.LOG;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.net.Uri;

/**
* This class called by CordovaActivity to play and record audio.
Expand All @@ -57,8 +55,10 @@ public class AudioHandler extends CordovaPlugin {

public static String TAG = "AudioHandler";
HashMap<String, AudioPlayer> players; // Audio player object
ArrayList<AudioPlayer> pausedForPhone; // Audio players that were paused when phone call came in
ArrayList<AudioPlayer> pausedForFocus; // Audio players that were paused when focus was lost
ArrayList<AudioPlayer> paused; // Audio players that were paused. Reasons:
boolean audioFocusLost = false; // paused when audiofocus was lost
boolean calling = false; // paused when calling
boolean activityFocusLost = false; // paused when activity got paused
private int origVolumeStream = -1;
private CallbackContext messageChannel;

Expand All @@ -77,8 +77,7 @@ public class AudioHandler extends CordovaPlugin {
*/
public AudioHandler() {
this.players = new HashMap<String, AudioPlayer>();
this.pausedForPhone = new ArrayList<AudioPlayer>();
this.pausedForFocus = new ArrayList<AudioPlayer>();
this.paused = new ArrayList<AudioPlayer>();
}


Expand Down Expand Up @@ -129,13 +128,20 @@ else if (action.equals("resumeRecordingAudio")) {
else if (action.equals("startPlayingAudio")) {
String target = args.getString(1);
String fileUriStr;
boolean playAudioWhenScreenIsLocked=true;
try {
Uri targetUri = resourceApi.remapUri(Uri.parse(target));
fileUriStr = targetUri.toString();
} catch (IllegalArgumentException e) {
fileUriStr = target;
}
this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr));
try {
JSONObject playArgs = new JSONObject(args.getString(2));
playAudioWhenScreenIsLocked = playArgs.getBoolean("playAudioWhenScreenIsLocked");
} catch (JSONException e) {
playAudioWhenScreenIsLocked = true;
}
this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr),playAudioWhenScreenIsLocked);
}
else if (action.equals("seekToAudio")) {
this.seekToAudio(args.getString(0), args.getInt(1));
Expand Down Expand Up @@ -225,21 +231,21 @@ public Object onMessage(String id, Object data) {
if ("ringing".equals(data) || "offhook".equals(data)) {

// Get all audio players and pause them
for (AudioPlayer audio : this.players.values()) {
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
this.pausedForPhone.add(audio);
audio.pausePlaying();
}
}
calling = true;
pauseAll();

}

// If phone idle, then resume playing those players we paused
else if ("idle".equals(data)) {
for (AudioPlayer audio : this.pausedForPhone) {
audio.startPlaying(null);
}
this.pausedForPhone.clear();
if(!audioFocusLost){
if (activityFocusLost) {
resumePlayingMarked();
}else {
resumePlayingAll();
}
}
calling = false;
}
}
return null;
Expand All @@ -250,14 +256,19 @@ else if ("idle".equals(data)) {
//--------------------------------------------------------------------------

private AudioPlayer getOrCreatePlayer(String id, String file) {
return getOrCreatePlayer(id,file,true);
}

private AudioPlayer getOrCreatePlayer(String id, String file, boolean playAudioWhenScreenIsLocked) {
AudioPlayer ret = players.get(id);
if (ret == null) {
if (players.isEmpty()) {
onFirstPlayerCreated();
}
ret = new AudioPlayer(this, id, file);
ret = new AudioPlayer(this, id, file, playAudioWhenScreenIsLocked);
players.put(id, ret);
}
ret.setPlayAudioWhenScreenIsLocked(playAudioWhenScreenIsLocked);
return ret;
}

Expand Down Expand Up @@ -315,8 +326,8 @@ public void resumeRecordingAudio(String id) {
* @param id The id of the audio player
* @param file The name of the audio file.
*/
public void startPlayingAudio(String id, String file) {
AudioPlayer audio = getOrCreatePlayer(id, file);
public void startPlayingAudio(String id, String file, boolean playAudioWhenScreenIsLocked) {
AudioPlayer audio = getOrCreatePlayer(id, file, playAudioWhenScreenIsLocked);
audio.startPlaying(file);
getAudioFocus();
}
Expand Down Expand Up @@ -400,22 +411,56 @@ else if (output == 1) {
}
}

public void pauseAllLostFocus() {
/**
* This method pauses all AudioPlayers.
* */
public void pauseAll() {
for (AudioPlayer audio : this.players.values()) {
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
this.pausedForFocus.add(audio);
this.paused.add(audio);
audio.pausePlaying();
}
}
}

public void resumeAllGainedFocus() {
for (AudioPlayer audio : this.pausedForFocus) {
/**
* This method pauses all AudioPlayers not marked with isPlayAudioWhenScreenIsLocked.
* */
public void pauseAudiosNotMarked() {
for (AudioPlayer audio : this.players.values()) {
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal() && !audio.isPlayAudioWhenScreenIsLocked()) {
this.paused.add(audio);
audio.pausePlaying();
}
}
}

/**
* Resume playing all paused audios
*/
public void resumePlayingAll() {
for (AudioPlayer audio : this.paused) {
audio.resumePlaying();
}
this.pausedForFocus.clear();
paused.clear();
}

/**
* Resume playing all audios marked with isPlayAudioWhenScreenIsLocked
*/
public void resumePlayingMarked() {
ArrayList<AudioPlayer> remove = new ArrayList<AudioPlayer>();
for (AudioPlayer audio : this.paused) {
if(audio.isPlayAudioWhenScreenIsLocked()){
audio.resumePlaying();
remove.add(audio);
}
}
paused.removeAll(remove);
}



/**
* Get the the audio focus
*/
Expand All @@ -425,10 +470,18 @@ public void onAudioFocusChange(int focusChange) {
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) :
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) :
case (AudioManager.AUDIOFOCUS_LOSS) :
pauseAllLostFocus();
pauseAll();
audioFocusLost = true;
break;
case (AudioManager.AUDIOFOCUS_GAIN):
resumeAllGainedFocus();
if (!calling) {
if(activityFocusLost){
resumePlayingMarked();
}else{
resumePlayingAll();
}
}
audioFocusLost = false;
break;
default:
break;
Expand Down Expand Up @@ -553,6 +606,22 @@ else if(PermissionHelper.hasPermission(this, permissions[RECORD_AUDIO]))

}

@Override
public void onResume(boolean multitasking) {
super.onResume(multitasking);
if (!(audioFocusLost||calling)) {
resumePlayingAll();
}
activityFocusLost = false;
}

@Override
public void onPause(boolean multitasking) {
activityFocusLost = true;
pauseAudiosNotMarked();
super.onPause(multitasking);
}

/**
* Get current amplitude of recording.
* @param id The id of the audio player
Expand Down
41 changes: 26 additions & 15 deletions src/android/AudioPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ Licensed to the Apache Software Foundation (ASF) under one
*/
package org.apache.cordova.media;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;

import org.apache.cordova.LOG;
import org.json.JSONException;
import org.json.JSONObject;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
Expand All @@ -26,19 +38,6 @@ Licensed to the Apache Software Foundation (ASF) under one
import android.media.MediaRecorder;
import android.os.Environment;

import org.apache.cordova.LOG;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.LinkedList;

/**
* This class implements the audio playback and recording capabilities used by Cordova.
* It is called by the AudioHandler Cordova class.
Expand Down Expand Up @@ -93,17 +92,29 @@ public enum STATE { MEDIA_NONE,
private boolean prepareOnly = true; // playback after file prepare flag
private int seekOnPrepared = 0; // seek to this location once media is prepared

/**
private boolean playAudioWhenScreenIsLocked = true; // If set to false the playback will be paused when app is paused

public boolean isPlayAudioWhenScreenIsLocked() {
return playAudioWhenScreenIsLocked;
}

public void setPlayAudioWhenScreenIsLocked(boolean playAudioWhenScreenIsLocked) {
this.playAudioWhenScreenIsLocked = playAudioWhenScreenIsLocked;
}

/**
* Constructor.
*
* @param handler The audio handler object
* @param id The id of this audio player
*/
public AudioPlayer(AudioHandler handler, String id, String file) {
public AudioPlayer(AudioHandler handler, String id, String file, boolean playAudioWhenScreenIsLocked) {
this.handler = handler;
this.id = id;
this.audioFile = file;
this.tempFiles = new LinkedList<String>();

this.playAudioWhenScreenIsLocked = playAudioWhenScreenIsLocked;
}

private String generateTempFile() {
Expand Down

0 comments on commit b55295c

Please sign in to comment.