Skip to content

Commit 39a6f91

Browse files
author
Buddy Reno
committed
Merge PR apache#137 for android playAudioWhenScreenIsLocked
1 parent ecd3a8d commit 39a6f91

File tree

2 files changed

+133
-53
lines changed

2 files changed

+133
-53
lines changed

src/android/AudioHandler.java

Lines changed: 107 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,27 @@ Licensed to the Apache Software Foundation (ASF) under one
1818
*/
1919
package org.apache.cordova.media;
2020

21-
import org.apache.cordova.CallbackContext;
22-
import org.apache.cordova.CordovaPlugin;
23-
import org.apache.cordova.CordovaResourceApi;
2421
import org.apache.cordova.PermissionHelper;
25-
26-
import android.Manifest;
27-
import android.content.Context;
28-
import android.content.pm.PackageManager;
29-
import android.media.AudioManager;
30-
import android.media.AudioManager.OnAudioFocusChangeListener;
31-
import android.net.Uri;
32-
import android.os.Build;
33-
3422
import java.security.Permission;
23+
3524
import java.util.ArrayList;
25+
import java.util.HashMap;
3626

27+
import org.apache.cordova.CallbackContext;
28+
import org.apache.cordova.CordovaPlugin;
29+
import org.apache.cordova.CordovaResourceApi;
3730
import org.apache.cordova.LOG;
3831
import org.apache.cordova.PluginResult;
3932
import org.json.JSONArray;
4033
import org.json.JSONException;
4134
import org.json.JSONObject;
4235

43-
import java.util.HashMap;
36+
import android.Manifest;
37+
import android.content.Context;
38+
import android.content.pm.PackageManager;
39+
import android.media.AudioManager;
40+
import android.media.AudioManager.OnAudioFocusChangeListener;
41+
import android.net.Uri;
4442

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

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

@@ -77,8 +77,7 @@ public class AudioHandler extends CordovaPlugin {
7777
*/
7878
public AudioHandler() {
7979
this.players = new HashMap<String, AudioPlayer>();
80-
this.pausedForPhone = new ArrayList<AudioPlayer>();
81-
this.pausedForFocus = new ArrayList<AudioPlayer>();
80+
this.paused = new ArrayList<AudioPlayer>();
8281
}
8382

8483

@@ -129,13 +128,20 @@ else if (action.equals("resumeRecordingAudio")) {
129128
else if (action.equals("startPlayingAudio")) {
130129
String target = args.getString(1);
131130
String fileUriStr;
131+
boolean playAudioWhenScreenIsLocked=true;
132132
try {
133133
Uri targetUri = resourceApi.remapUri(Uri.parse(target));
134134
fileUriStr = targetUri.toString();
135135
} catch (IllegalArgumentException e) {
136136
fileUriStr = target;
137137
}
138-
this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr));
138+
try {
139+
JSONObject playArgs = new JSONObject(args.getString(2));
140+
playAudioWhenScreenIsLocked = playArgs.getBoolean("playAudioWhenScreenIsLocked");
141+
} catch (JSONException e) {
142+
playAudioWhenScreenIsLocked = true;
143+
}
144+
this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr),playAudioWhenScreenIsLocked);
139145
}
140146
else if (action.equals("seekToAudio")) {
141147
this.seekToAudio(args.getString(0), args.getInt(1));
@@ -225,21 +231,21 @@ public Object onMessage(String id, Object data) {
225231
if ("ringing".equals(data) || "offhook".equals(data)) {
226232

227233
// Get all audio players and pause them
228-
for (AudioPlayer audio : this.players.values()) {
229-
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
230-
this.pausedForPhone.add(audio);
231-
audio.pausePlaying();
232-
}
233-
}
234+
calling = true;
235+
pauseAll();
234236

235237
}
236238

237239
// If phone idle, then resume playing those players we paused
238240
else if ("idle".equals(data)) {
239-
for (AudioPlayer audio : this.pausedForPhone) {
240-
audio.startPlaying(null);
241-
}
242-
this.pausedForPhone.clear();
241+
if(!audioFocusLost){
242+
if (activityFocusLost) {
243+
resumePlayingMarked();
244+
}else {
245+
resumePlayingAll();
246+
}
247+
}
248+
calling = false;
243249
}
244250
}
245251
return null;
@@ -250,14 +256,19 @@ else if ("idle".equals(data)) {
250256
//--------------------------------------------------------------------------
251257

252258
private AudioPlayer getOrCreatePlayer(String id, String file) {
259+
return getOrCreatePlayer(id,file,true);
260+
}
261+
262+
private AudioPlayer getOrCreatePlayer(String id, String file, boolean playAudioWhenScreenIsLocked) {
253263
AudioPlayer ret = players.get(id);
254264
if (ret == null) {
255265
if (players.isEmpty()) {
256266
onFirstPlayerCreated();
257267
}
258-
ret = new AudioPlayer(this, id, file);
268+
ret = new AudioPlayer(this, id, file, playAudioWhenScreenIsLocked);
259269
players.put(id, ret);
260270
}
271+
ret.setPlayAudioWhenScreenIsLocked(playAudioWhenScreenIsLocked);
261272
return ret;
262273
}
263274

@@ -315,8 +326,8 @@ public void resumeRecordingAudio(String id) {
315326
* @param id The id of the audio player
316327
* @param file The name of the audio file.
317328
*/
318-
public void startPlayingAudio(String id, String file) {
319-
AudioPlayer audio = getOrCreatePlayer(id, file);
329+
public void startPlayingAudio(String id, String file, boolean playAudioWhenScreenIsLocked) {
330+
AudioPlayer audio = getOrCreatePlayer(id, file, playAudioWhenScreenIsLocked);
320331
audio.startPlaying(file);
321332
getAudioFocus();
322333
}
@@ -400,22 +411,56 @@ else if (output == 1) {
400411
}
401412
}
402413

403-
public void pauseAllLostFocus() {
414+
/**
415+
* This method pauses all AudioPlayers.
416+
* */
417+
public void pauseAll() {
404418
for (AudioPlayer audio : this.players.values()) {
405419
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
406-
this.pausedForFocus.add(audio);
420+
this.paused.add(audio);
407421
audio.pausePlaying();
408422
}
409423
}
410424
}
411425

412-
public void resumeAllGainedFocus() {
413-
for (AudioPlayer audio : this.pausedForFocus) {
426+
/**
427+
* This method pauses all AudioPlayers not marked with isPlayAudioWhenScreenIsLocked.
428+
* */
429+
public void pauseAudiosNotMarked() {
430+
for (AudioPlayer audio : this.players.values()) {
431+
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal() && !audio.isPlayAudioWhenScreenIsLocked()) {
432+
this.paused.add(audio);
433+
audio.pausePlaying();
434+
}
435+
}
436+
}
437+
438+
/**
439+
* Resume playing all paused audios
440+
*/
441+
public void resumePlayingAll() {
442+
for (AudioPlayer audio : this.paused) {
414443
audio.resumePlaying();
415444
}
416-
this.pausedForFocus.clear();
445+
paused.clear();
417446
}
418447

448+
/**
449+
* Resume playing all audios marked with isPlayAudioWhenScreenIsLocked
450+
*/
451+
public void resumePlayingMarked() {
452+
ArrayList<AudioPlayer> remove = new ArrayList<AudioPlayer>();
453+
for (AudioPlayer audio : this.paused) {
454+
if(audio.isPlayAudioWhenScreenIsLocked()){
455+
audio.resumePlaying();
456+
remove.add(audio);
457+
}
458+
}
459+
paused.removeAll(remove);
460+
}
461+
462+
463+
419464
/**
420465
* Get the the audio focus
421466
*/
@@ -425,10 +470,18 @@ public void onAudioFocusChange(int focusChange) {
425470
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) :
426471
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) :
427472
case (AudioManager.AUDIOFOCUS_LOSS) :
428-
pauseAllLostFocus();
473+
pauseAll();
474+
audioFocusLost = true;
429475
break;
430476
case (AudioManager.AUDIOFOCUS_GAIN):
431-
resumeAllGainedFocus();
477+
if (!calling) {
478+
if(activityFocusLost){
479+
resumePlayingMarked();
480+
}else{
481+
resumePlayingAll();
482+
}
483+
}
484+
audioFocusLost = false;
432485
break;
433486
default:
434487
break;
@@ -553,6 +606,22 @@ else if(PermissionHelper.hasPermission(this, permissions[RECORD_AUDIO]))
553606

554607
}
555608

609+
@Override
610+
public void onResume(boolean multitasking) {
611+
super.onResume(multitasking);
612+
if (!(audioFocusLost||calling)) {
613+
resumePlayingAll();
614+
}
615+
activityFocusLost = false;
616+
}
617+
618+
@Override
619+
public void onPause(boolean multitasking) {
620+
activityFocusLost = true;
621+
pauseAudiosNotMarked();
622+
super.onPause(multitasking);
623+
}
624+
556625
/**
557626
* Get current amplitude of recording.
558627
* @param id The id of the audio player

src/android/AudioPlayer.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ Licensed to the Apache Software Foundation (ASF) under one
1818
*/
1919
package org.apache.cordova.media;
2020

21+
import java.io.File;
22+
import java.io.FileInputStream;
23+
import java.io.FileOutputStream;
24+
import java.io.IOException;
25+
import java.io.InputStream;
26+
import java.io.OutputStream;
27+
import java.util.LinkedList;
28+
29+
import org.apache.cordova.LOG;
30+
import org.json.JSONException;
31+
import org.json.JSONObject;
32+
2133
import android.media.AudioManager;
2234
import android.media.MediaPlayer;
2335
import android.media.MediaPlayer.OnCompletionListener;
@@ -26,19 +38,6 @@ Licensed to the Apache Software Foundation (ASF) under one
2638
import android.media.MediaRecorder;
2739
import android.os.Environment;
2840

29-
import org.apache.cordova.LOG;
30-
31-
import org.json.JSONException;
32-
import org.json.JSONObject;
33-
34-
import java.io.File;
35-
import java.io.FileInputStream;
36-
import java.io.FileOutputStream;
37-
import java.io.InputStream;
38-
import java.io.OutputStream;
39-
import java.io.IOException;
40-
import java.util.LinkedList;
41-
4241
/**
4342
* This class implements the audio playback and recording capabilities used by Cordova.
4443
* It is called by the AudioHandler Cordova class.
@@ -93,17 +92,29 @@ public enum STATE { MEDIA_NONE,
9392
private boolean prepareOnly = true; // playback after file prepare flag
9493
private int seekOnPrepared = 0; // seek to this location once media is prepared
9594

96-
/**
95+
private boolean playAudioWhenScreenIsLocked = true; // If set to false the playback will be paused when app is paused
96+
97+
public boolean isPlayAudioWhenScreenIsLocked() {
98+
return playAudioWhenScreenIsLocked;
99+
}
100+
101+
public void setPlayAudioWhenScreenIsLocked(boolean playAudioWhenScreenIsLocked) {
102+
this.playAudioWhenScreenIsLocked = playAudioWhenScreenIsLocked;
103+
}
104+
105+
/**
97106
* Constructor.
98107
*
99108
* @param handler The audio handler object
100109
* @param id The id of this audio player
101110
*/
102-
public AudioPlayer(AudioHandler handler, String id, String file) {
111+
public AudioPlayer(AudioHandler handler, String id, String file, boolean playAudioWhenScreenIsLocked) {
103112
this.handler = handler;
104113
this.id = id;
105114
this.audioFile = file;
106115
this.tempFiles = new LinkedList<String>();
116+
117+
this.playAudioWhenScreenIsLocked = playAudioWhenScreenIsLocked;
107118
}
108119

109120
private String generateTempFile() {

0 commit comments

Comments
 (0)