[ https://issues.apache.org/jira/browse/CB-13502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16637223#comment-16637223 ]
ASF GitHub Bot commented on CB-13502: ------------------------------------- janpio closed pull request #152: CB-13502: (android) Implementation of setRate method for Android Marshmallow and later URL: https://github.com/apache/cordova-plugin-media/pull/152 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/.travis.yml b/.travis.yml index 59a576db..dcad4ad5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ addons: secure: M4uBGUMbanDtCBrNktJhEwNSLL0UsOV3IoINqW3GRupX7Mr13MBZzsORm4HVbdbPxQ6Bf2LhyJ/fabQRsOoJrCokgWwfKkigztQcMFeLNao9liBRA6kuQOh5/rdfoULpu96GvlYzB4ddgSBSSGQW3DesaKC/BpTXnvQ4OnXo5e4= env: global: - - SAUCE_USERNAME=snay + - SAUCE_USERNAME=jh3141 - TRAVIS_NODE_VERSION="4.2" matrix: include: diff --git a/README.md b/README.md index 577cd388..41b894cb 100644 --- a/README.md +++ b/README.md @@ -23,36 +23,25 @@ description: Record and play audio on the device. |AppVeyor|Travis CI| |:-:|:-:| -|[![Build status](https://ci.appveyor.com/api/projects/status/github/apache/cordova-plugin-media?branch=master)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/cordova-plugin-media)|[![Build Status](https://travis-ci.org/apache/cordova-plugin-media.svg?branch=master)](https://travis-ci.org/apache/cordova-plugin-media)| +|[![Build status](https://ci.appveyor.com/api/projects/status/github/apache/cordova-plugin-media?branch=master)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/cordova-plugin-media)|[![Build Status](https://travis-ci.org/jh3141/cordova-plugin-media.svg?branch=master)](https://travis-ci.org/jh3141/cordova-plugin-media)| # cordova-plugin-media -This plugin provides the ability to record and play back audio files on a device. +This is a forked version of the cordova-plugin-media plugin, which provides the ability to record +and play back audio files on a device. This fork adds the following changes: -__NOTE__: The current implementation does not adhere to a W3C -specification for media capture, and is provided for convenience only. -A future implementation will adhere to the latest W3C specification -and may deprecate the current APIs. - -This plugin defines a global `Media` Constructor. - -Although in the global scope, it is not available until after the `deviceready` event. - -```js -document.addEventListener("deviceready", onDeviceReady, false); -function onDeviceReady() { - console.log(Media); -} -``` - -Report issues with this plugin on the [Apache Cordova issue tracker](https://issues.apache.org/jira/issues/?jql=project%20%3D%20CB%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20resolution%20%3D%20Unresolved%20AND%20component%20%3D%20%22cordova-plugin-media%22%20ORDER%20BY%20priority%20DESC%2C%20summary%20ASC%2C%20updatedDate%20DESC) +* Support the `setRate` API under Android +* Fix broken tests +Additional updates are planned for better handling of background playing, and supporting background +application use. If they aren't available here yet, there may be development versions in branches +that haven't been merged yet; have a look at those if you're interested. ## Installation ```bash -cordova plugin add cordova-plugin-media +cordova plugin add https://github.com/jh3141/cordova-plugin-media ``` ## Supported Platforms @@ -322,9 +311,13 @@ function recordAudio() { Starts or resumes playing an audio file. ```js -media.play(); +media.play(options); ``` +* Options specifies optional settings for player behaviour, and may be omitted if + the defaults are to be used. See the platform-specific descriptions below for + available options. + ### Quick Example ```js diff --git a/src/android/AudioHandler.java b/src/android/AudioHandler.java index 9e734c44..f3ad938d 100644 --- a/src/android/AudioHandler.java +++ b/src/android/AudioHandler.java @@ -129,13 +129,20 @@ else if (action.equals("resumeRecordingAudio")) { else if (action.equals("startPlayingAudio")) { String target = args.getString(1); String fileUriStr; + boolean ignoreFocusLost; 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 { + ignoreFocusLost = args.getJSONObject(2).getBoolean("ignoreFocusLost"); + } catch (JSONException ignored) { + ignoreFocusLost = false; + } + + this.startPlayingAudio(args.getString(0), FileHelper.stripFileProtocol(fileUriStr), ignoreFocusLost); } else if (action.equals("seekToAudio")) { this.seekToAudio(args.getString(0), args.getInt(1)); @@ -178,6 +185,12 @@ else if (action.equals("messageChannel")) { float f = this.getCurrentAmplitudeAudio(args.getString(0)); callbackContext.sendPluginResult(new PluginResult(status, f)); return true; + } else if (action.equals("setRate")) { + try { + this.setRate(args.getString(0), Float.parseFloat(args.getString(1))); + } catch (NumberFormatException nfe) { + //no-op + } } else { // Unrecognized action. return false; @@ -314,9 +327,11 @@ public void resumeRecordingAudio(String id) { * Start or resume playing audio file. * @param id The id of the audio player * @param file The name of the audio file. + * @param ignoreFocusLost If true, do not suspend playback when focus is lost */ - public void startPlayingAudio(String id, String file) { + public void startPlayingAudio(String id, String file, boolean ignoreFocusLost) { AudioPlayer audio = getOrCreatePlayer(id, file); + audio.setIgnoreFocusLost (ignoreFocusLost) audio.startPlaying(file); getAudioFocus(); } @@ -402,7 +417,7 @@ else if (output == 1) { public void pauseAllLostFocus() { for (AudioPlayer audio : this.players.values()) { - if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) { + if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal() && !audio.getIgnoreLostFocus()) { this.pausedForFocus.add(audio); audio.pausePlaying(); } @@ -487,6 +502,23 @@ public void setVolume(String id, float volume) { } } + /** + * Set the playback rate for an audio player + * + * @param id The id of the audio player + * @param rate Playback rate (where 1.0 is normal speed) + */ + public void setRate(String id, float rate) { + String TAG4 = "AudioHandler.setRate(): Error : "; + + AudioPlayer audio = this.players.get(id); + if (audio != null) { + audio.setRate(rate); + } else { + LOG.e(TAG4,"Unknown Audio Player " + id); + } + } + private void onFirstPlayerCreated() { origVolumeStream = cordova.getActivity().getVolumeControlStream(); cordova.getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC); diff --git a/src/android/AudioPlayer.java b/src/android/AudioPlayer.java index 861421e7..2d788bec 100644 --- a/src/android/AudioPlayer.java +++ b/src/android/AudioPlayer.java @@ -92,6 +92,8 @@ Licensed to the Apache Software Foundation (ASF) under one private MediaPlayer player = null; // Audio player object private boolean prepareOnly = true; // playback after file prepare flag private int seekOnPrepared = 0; // seek to this location once media is prepared + private float setRateOnPrepared = -1; + private boolean ignoreFocusLost = false; /** * Constructor. @@ -446,6 +448,9 @@ public void onPrepared(MediaPlayer player) { this.player.setOnCompletionListener(this); // seek to any location received while not prepared this.seekToPlaying(this.seekOnPrepared); + // apply any playback rate received while not prepared + if (setRateOnPrepared >= 0) + this.player.setPlaybackParams (this.player.getPlaybackParams().setSpeed(setRateOnPrepared)); // If start playing after prepared if (!this.prepareOnly) { this.player.start(); @@ -541,6 +546,23 @@ public void setVolume(float volume) { } } + /** + * Set the playback rate for the player (ignored on API < 23) + * + * @param volume + */ + public void setRate(float rate) { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) { + LOG.d(LOG_TAG, "AudioPlayer Warning: Request to set playback rate not supported on current OS version"); + return; + } + if (this.player != null) { + this.player.setPlaybackParams (this.player.getPlaybackParams().setSpeed(rate)); + } else { + setRateOnPrepared = rate; + } + } + /** * attempts to put the player in play mode * @return true if in playmode, false otherwise @@ -719,4 +741,22 @@ public float getCurrentAmplitude() { } return 0; } + + /** + * Sets the flag controlling whether this player should be paused whenever + * audio focus is lost. Default false => pause is performed. + */ + public void setIgnoreFocusLost (boolean ignoreFocusLost) + { + this.ignoreFocusLost = ignoreFocusLost; + } + + /** + * Gets the flag controlling whether this player should be paused whenever + * audio focus is lost. Default false => pause is performed. + */ + public boolean getIgnoreLostFocus () + { + return ignoreFocusLost; + } } diff --git a/tests/tests.js b/tests/tests.js index 218f2a95..0f0159e7 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -27,7 +27,7 @@ var ACTUAL_PLAYBACK_TEST_TIMEOUT = 2 * 60 * 1000; var WEB_MP3_FILE = 'https://cordova.apache.org/downloads/BlueZedEx.mp3'; -var WEB_MP3_STREAM = 'http://c22033-l.i.core.cdn.streamfarm.net/22033mdr/live/3087mdr_figaro/ch_classic_128.mp3'; +var WEB_MP3_STREAM = 'http://forever.fm/all.mp3'; var isWindows = cordova.platformId === 'windows8' || cordova.platformId === 'windows'; var isBrowser = cordova.platformId === 'browser'; @@ -36,6 +36,14 @@ var isBrowser = cordova.platformId === 'browser'; // the case for Sauce Labs emulators - see CB-11430) var isAudioSupported = isWindows ? !!Windows.Media.Devices.MediaDevice.getDefaultAudioRenderId(Windows.Media.Devices.AudioDeviceRole.default) : cordova.platformId === 'ios' ? !window.SAUCELABS_ENV : true; +// Detect OS version when running on Android +var androidVersion = null; +if (cordova.platformId === 'android') { + var ua = navigator.userAgent; + var androidStart = ua.indexOf('Android '); + var versionString = ua.substring(androidStart + 8, ua.indexOf(';', androidStart)); + androidVersion = versionString.split(".").map(function(x) { return x/1; }); +} exports.defineAutoTests = function () { var failed = function (done, msg, context) { @@ -376,7 +384,9 @@ exports.defineAutoTests = function () { }); it("media.spec.24 playback rate should be set properly using setRate", function (done) { - if (cordova.platformId !== 'ios') { + if (cordova.platformId !== 'ios' && + (cordova.platformId !== 'android' || androidVersion[0] <= 6)) + { expect(true).toFailWithMessage('Platform does not supported this feature'); pending(); } diff --git a/www/Media.js b/www/Media.js index 5806b9f6..8d84ea9a 100644 --- a/www/Media.js +++ b/www/Media.js @@ -170,7 +170,7 @@ Media.prototype.setVolume = function(volume) { * Adjust the playback rate. */ Media.prototype.setRate = function(rate) { - if (cordova.platformId === 'ios'){ + if (cordova.platformId === 'ios' || cordova.platformId === "android"){ exec(null, null, "Media", "setRate", [this.id, rate]); } else { console.warn('media.setRate method is currently not supported for', cordova.platformId, 'platform.'); ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org > Android - add support for "setRate" method already available on iOS > ------------------------------------------------------------------- > > Key: CB-13502 > URL: https://issues.apache.org/jira/browse/CB-13502 > Project: Apache Cordova > Issue Type: Improvement > Components: cordova-plugin-media > Reporter: Julian Hall > Priority: Minor > > The iOS media plugin supports a method "setRate" which changes the playback > rate. Android has support for this feature in the MediaPlayer class used by > the media plugin since API version 23 (Marshmallow), therefore supporting > this method there is very easy. -- This message was sent by Atlassian JIRA (v7.6.3#76005) --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@cordova.apache.org For additional commands, e-mail: issues-h...@cordova.apache.org