Skip to content

Instantly share code, notes, and snippets.

@dyazincahya
Created June 10, 2024 06:06
Show Gist options
  • Save dyazincahya/2f965b1ff338e8efb238a687b5143c4e to your computer and use it in GitHub Desktop.
Save dyazincahya/2f965b1ff338e8efb238a687b5143c4e to your computer and use it in GitHub Desktop.
Audio Player Utils for Nativescript 8 (core JS) (Android)

Dependency

Before using this Utils, yout must add native depedencies in App_Resources/Android/app.gradle

implementation 'com.google.android.exoplayer:exoplayer:2.19.1'

Usage

TS Import

import { AudioPlayer } from '~/util_audio_player';

JS require

const AudioPlayer = require("./util_audio_player").AudioPlayer; 

Example

const player = new AudioPlayer();
player.openUrl("https://www.example.com/path-to-audio.mp3", {
  autoplay: true,
  onError: function (error) {
    console.error("Audio player error:", error);
  },
  onFinished: function () {
    console.log("Audio playback finished");
  },
});

// To play
player.play();

// To pause
player.pause();

// To release resources
player.release();

Usage Explanation

Import and Initialize:

  • Import the AudioPlayer class.
  • Create a new instance of AudioPlayer.

Open URL and Play:

  • Call openUrl with the audio URL and options.
  • The options can include autoplay, onError, and onFinished callbacks.

Control Playback:

  • Use play() to start playback.
  • Use pause() to pause playback.
  • Use release() to release resources when done.

This implementation covers basic usage and provides flexibility for additional functionalities if needed.

// @ts-nocheck
const { Utils } = require("@nativescript/core");
function AudioPlayer() {
this.player = null;
this._context = Utils.android.getApplicationContext();
this._isPlaying = false;
this._onFinishedCallback = null;
this._onErrorCallback = null;
}
AudioPlayer.prototype.openUrl = function (src, options) {
this.release();
const bm =
new com.google.android.exoplayer2.upstream.DefaultBandwidthMeter.Builder(
this._context
).build();
const trackSelection =
new com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection.Factory();
const trackSelector =
new com.google.android.exoplayer2.trackselection.DefaultTrackSelector(
this._context,
trackSelection
);
const loadControl = new com.google.android.exoplayer2.DefaultLoadControl();
const builder = new com.google.android.exoplayer2.ExoPlayer.Builder(
this._context
);
builder.setTrackSelector(trackSelector);
builder.setLoadControl(loadControl);
this.player = builder.build();
this._setupListeners();
this._onErrorCallback = options && options.onError;
this._onFinishedCallback = options && options.onFinished;
const userAgent = com.google.android.exoplayer2.util.Util.getUserAgent(
this._context,
Utils.android.getApplicationContext().getPackageName()
);
const dsf =
new com.google.android.exoplayer2.upstream.DefaultDataSourceFactory(
this._context,
userAgent,
bm
);
const uri = android.net.Uri.parse(src);
const mediaItem = com.google.android.exoplayer2.MediaItem.fromUri(uri);
const vs =
new com.google.android.exoplayer2.source.ProgressiveMediaSource.Factory(
dsf
).createMediaSource(mediaItem);
this.player.setMediaSource(vs);
if (options && options.autoplay) {
this.player.prepare();
this.player.setPlayWhenReady(true);
}
};
AudioPlayer.prototype.release = function () {
if (this.player) {
this.player.stop();
this.player.release();
this.player = null;
const am = this._context.getSystemService(
android.content.Context.AUDIO_SERVICE
);
if (com.google.android.exoplayer2.util.Util.SDK_INT >= 26) {
const afr = new android.media.AudioFocusRequest.Builder(
android.media.AudioManager.AUDIOFOCUS_GAIN
).build();
am.abandonAudioFocusRequest(afr);
} else {
am.abandonAudioFocus(null);
}
}
};
AudioPlayer.prototype.play = function () {
if (this.player) {
this._isPlaying = true;
this.player.prepare();
this.player.setPlayWhenReady(true);
}
};
AudioPlayer.prototype.pause = function () {
if (this.player) {
this._isPlaying = false;
this.player.setPlayWhenReady(false);
}
};
AudioPlayer.prototype.getCurrentTime = function () {
if (!this.player) {
return 0;
}
return this.player.getCurrentPosition();
};
AudioPlayer.prototype._setupListeners = function () {
const playerListener = new com.google.android.exoplayer2.Player.Listener({
onEvents: function (_player, _events) {
/* required in listener implementation */
},
onTimelineChanged: function (_timeline, _manifest) {
/* required in listener implementation */
},
onMediaItemTransition: function (_mediaItem, _reason) {
/* required in listener implementation */
},
onTracksChanged: function (_trackGroups, _trackSelections) {
/* required in listener implementation */
},
onTracksInfoChanged: function (_tracksInfo) {
/* required in listener implementation */
},
onMediaMetadataChanged: function (_mediaMetadata) {
/* required in listener implementation */
},
onPlaylistMetadataChanged: function (_mediaMetadata) {
/* required in listener implementation */
},
onIsLoadingChanged: function (_isLoading) {
/* required in listener implementation */
},
onLoadingChanged: function (_isLoading) {
/* required in listener implementation */
},
onAvailableCommandsChanged: function (_availableCommands) {
/* required in listener implementation */
},
onTrackSelectionParametersChanged: function (_parameters) {
/* required in listener implementation */
},
onPlayerStateChanged: function (playWhenReady, playbackState) {
/* required in listener implementation */
},
onPlaybackStateChanged: function (playbackState) {
if (playbackState === com.google.android.exoplayer2.Player.STATE_ENDED) {
if (this._onFinishedCallback) {
this._onFinishedCallback();
}
}
},
onPlayWhenReadyChanged: function (playWhenReady, _reason) {
/* required in listener implementation */
},
onPlaybackSuppressionReasonChanged: function (_playbackSuppressionReason) {
/* required in listener implementation */
},
onIsPlayingChanged: function (_isPlaying) {
/* required in listener implementation */
},
onRepeatModeChanged: function (_repeatMode) {
/* required in listener implementation */
},
onShuffleModeEnabledChanged: function (_shuffleModeEnabled) {
/* required in listener implementation */
},
onPlayerError: function (error) {
if (this._onErrorCallback) {
this._onErrorCallback(error);
}
},
onPlayerErrorChanged: function (_error) {
/* required in listener implementation */
},
onPositionDiscontinuity: function (
_reasonOrOldPosition,
_newPosition,
_reason
) {
/* required in listener implementation */
},
onPlaybackParametersChanged: function (_playbackParameters) {
/* required in listener implementation */
},
onSeekBackIncrementChanged: function (_param0) {
/* required in listener implementation */
},
onSeekForwardIncrementChanged: function (_seekBackIncrementMs) {
/* required in listener implementation */
},
onMaxSeekToPreviousPositionChanged: function (_maxSeekToPreviousPositionMs) {
/* required in listener implementation */
},
onSeekProcessed: function () {
/* required in listener implementation */
},
onAudioSessionIdChanged: function (_audioSessionId) {
/* required in listener implementation */
},
onAudioAttributesChanged: function (_audioAttributes) {
/* required in listener implementation */
},
onVolumeChanged: function (_volume) {
/* required in listener implementation */
},
onSkipSilenceEnabledChanged: function (_skipSilenceEnabled) {
/* required in listener implementation */
},
onDeviceInfoChanged: function (_deviceInfo) {
/* required in listener implementation */
},
onDeviceVolumeChanged: function (_volume, _muted) {
/* required in listener implementation */
},
onVideoSizeChanged: function (_videoSize) {
/* required in listener implementation */
},
onSurfaceSizeChanged: function (_width, _height) {
/* required in listener implementation */
},
onRenderedFirstFrame: function () {
/* required in listener implementation */
},
onCues: function (_cues) {
/* required in listener implementation */
},
onMetadata: function (_metadata) {
/* required in listener implementation */
},
});
if (this.player) {
this.player.addListener(playerListener);
}
};
exports.AudioPlayer = AudioPlayer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment