Android Media Player Streaming not working - android

I have created one streaming audio application which is working on some Android devices but except moto g (6.0.1)API.
Exception: IOException OR MEDIA_ERROR_SYSTEM "error : (1, -2147483648)"
Code:
URL url = new URL("streaming extracted url");
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
String urlStr = uri.toASCIIString();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(urlStr);
player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
}
});
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.reset();
}
});
player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
});
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
Can anyone please help me whats going wrong in this? Do I missing something?

I have had a similar and inexplicable issue. I am using a simple MediaPlayer to stream audio from a site. This works perfectly on a Samsung Galaxy S4 (Android 5.0.1), but on Pixel (Android 8.1.0) the audio won't play.
I am loading the URL on a play button click, showing a progress spinner until the MediaPlayer onPrepared listener is triggered. When prepared, I'm hiding the progress bar, and starting playback.
On Pixel, the normal loading / streaming time elapses (so I guess the file is being prepared!) onPrepared is triggered, no errors are shown, but the audio is never played!
Our server uses a self signed certificate which I thought might have been the issue, but even accessing the file over http it won't play on Pixel. I have also confirmed it's not a codec issue, as moving the file to Google Drive and playing with a direct link in my app the file plays back fine.
I am not sure if it's a server based issue, but all other files (images etc) are served and display fine (using Glide), and the file is served and can be viewed in Chrome via the same URL fed into the MediaPlayer!
I have just now moved to ExoPlayer, and it's playing fine on both devices .. so I guess this is the way forward!
Add dependency
compile 'com.google.android.exoplayer:exoplayer-core:2.6.1'
When play button is clicked, I'm loading Audio if not already loaded, otherwise starting playback
if (player == null) {
loadAudio();
} else {
player.setPlayWhenReady(true);
}
And my loadAudio()
private void loadAudio() {
String userAgent = Util.getUserAgent(getActivity(), "SimpleExoPlayer");
Uri uri = Uri.parse(audioUrl);
DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
true);
// This is the MediaSource representing the media to be played.
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
TrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector);
player.addListener(this);
player.prepare(mediaSource);
player.setPlayWhenReady(true);
}
... and the ExoPlayer listeners for state, so I can swap play / pause buttons in UI on completion etc
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_BUFFERING:
audioProgress.setVisibility(View.VISIBLE);
break;
case Player.STATE_ENDED:
handler.removeCallbacks(UpdateAudioTime);
buttonControllerPlay.setVisibility(View.VISIBLE);
buttonControllerPause.setVisibility(View.GONE);
seekBar.setProgress(0);
break;
case Player.STATE_IDLE:
break;
case Player.STATE_READY:
audioProgress.setVisibility(View.GONE);
finalTime = player.getDuration();
startTime = player.getCurrentPosition();
seekBar.setMax((int) finalTime);
seekBar.setProgress((int) startTime);
handler.postDelayed(UpdateAudioTime, 100);
break;
default:
break;
}
}
Remember to release the player on stop / destroy
Hopefully can help someone out there who is scratching their head as much as I was!

I've used the following code to stream audio on a Moto G5 (Android 7.0) and it is working fine:
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
mediaPlayer.setAudioAttributes(audioAttributes)
This might explain the issue:
Application developers should use audio attributes when creating or
updating applications for Android 5.0. However, applications are not
required to take advantage of attributes; they can handle legacy
stream types only or remain unaware of attributes (i.e. a generic
media player that doesn't know anything about the content it's
playing).
In such cases, the framework maintains backwards compatibility with
older devices and Android releases by automatically translating legacy
audio stream types to audio attributes. However, the framework does
not enforce or guarantee this mapping across devices, manufacturers,
or Android releases.
Source: https://source.android.com/devices/audio/attributes

Related

MediaPlayer error 100 & 38 while using two MediaPlayer objects

I'm trying to build a game which plays some sounds effects on click & at the same time music in the background.
I tried implementing this with two MediaPlayer objects.
The first one, which served for the effects on click works great.
The second one however sometimes logs error 100, sometimes error 38. No sound at all.
Variables
private MediaPlayer mEffects;
private MediaPlayer mpSoundBackground;
Implementation of the sound media player:
mpSoundBackground = MediaPlayer.create(MainActivity.this, R.raw.soundbackground1small);
mpSoundBackground.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Logger.d("prepared");
musicPrepared = true;
}
});
mpSoundBackground.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Logger.d("error "+what);
return false;
}
});
if (musicPrepared) {
mpSoundBackground.start();
Logger.d("music is prepared");
} else {
Logger.d("music is not prepared");
}
Implementation of the effects Media Player:
stopPlaying();
mEffects= MediaPlayer.create(MainActivity.this, R.raw.soundhit);
mEffects.start();
private void stopPlaying() {
if (mEffects!= null) {
mEffects.stop();
mEffects.release();
mEffects= null;
}
}
Update
To add to the confusion: It does seem to work in emulator
(Genymotion), but does not work on my OnePlus One, running Lollipop
You need to use the setOnPreparedListener method for both players. also if you want to play a sound on clicks consider using SoundPool.
Also in the public void onPrepared(MediaPlayer mp) method, you can use mp.start there is no need for that flag, since you can not know for sure that it is prepared once you reach that prepared flag
I couldn't make the errors go away, until I reconverted my soundfile to MP3.
Now it plays both on device & simulator without any problems.
Moral of this story: if you are running into errors, try a few encodings of the same file (possibly a few file sizes too!), it might be the solution.

ExoPlayer - play 10 files one after another

I have 10 video i need to play, once one is done, the next one starts to play.
I'm using Google's ExoPlayer, I use the example in the DEMO # GitHub.
I can play 1 video but if i try to play the next one, it wont start.
If i try to reInit the player, and the start playing again, it crashes.
private void loadvideo() {
Uri uri = Uri.parse(VIDEO_LIBRARY_URL + currentVideo + ".mp4");
sampleSource = new FrameworkSampleSource(this, uri, null, 2);
// 1. Instantiate the player.
// 2. Construct renderers.
videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
// 3. Inject the renderers through prepare.
player.prepare(videoRenderer, audioRenderer);
// 4. Pass the surface to the video renderer.
surface = surfaceView.getHolder().getSurface();
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
// 5. Start playback.
player.setPlayWhenReady(true);
player.addListener(new ExoPlayer.Listener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.d(TAG, "onPlayerStateChanged + " + playbackState);
if (playbackState == ExoPlayer.STATE_ENDED) {
currentVideo++;
loadNextVideo();
}
}
#Override
public void onPlayWhenReadyCommitted() {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
});
}
What am i doing wrong?
How can i play videos continuity?
Thanks.
You can reuse the ExoPlayer up until the point that you call release(), and then it should no longer be used.
To change the media that it is currently playing, you essentially need to perform the following steps:
// ...enable autoplay...
player.stop();
player.seekTo(0L);
player.prepare(renderers);
Creating the renderers is a little bit more involved, but that's the flow you should follow and the player should be able to play back to back videos.
I'm using Exoplayer change mp4 video success. I use the example in the DEMO.
1.DEMO project in DemoPlayer.java:
private final RendererBuilder rendererBuilder;
//remove final,then modify that:
private RendererBuilder rendererBuilder;
//and add the set method:
public void setRendererBuilder(RendererBuilder rendererBuilder){
this.rendererBuilder = rendererBuilder;
}
//finally,add stop method
public void stop(){
player.stop();
}
2.DEMO project in PlayerActivity.java:
add method:
private void changeVideo(){
player.stop();
player.seekTo(0L);
//you must change your contentUri before invoke getRendererBuilder();
player.setRendererBuilder(getRendererBuilder());
player.prepare();
playerNeedsPrepare = false;
}
remember change param contentUri before invoke changeVideo method.
Use ConcatenatingMediaSource to play files in sequence.
For example, for playing 2 media Uris (firstVideoUri and secondVideoUri), use this code:
MediaSource firstSource =
new ExtractorMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource =
new ExtractorMediaSource.Factory(...).createMediaSource(secondVideoUri);
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(firstSourceTwice, secondSource);
And then use concatenatedSource to play media files sequentially.
OK, Answering my own question.
on the example, google init the ExoPlayer at OnResume().
i had to re-init for every video like that:
player = ExoPlayer.Factory.newInstance(2, 1000, 5000);
if someone has a better idea, please let me know.
There is another solution, you could refer to ConcatenatingMediaSource to achieve auto play next media.
In Demo App example :
1. Launch ExoPlayer
2. Select Playlists
3. Choose Cats->Dogs

Play audio and video at the same time in Android

I'm trying to play two different files at the same time.
I have tried to find players and tried to extend the default player achieving the same but couldn't get success in that. so please help me with it, by letting me know what's the best way to play audio file and video at the same time?
The reason I'm taking separate files is to save space, because the app will be localized, having multiple audio files for each language instead of having multiple videos saves space. That's important because android doesn't allow the download of app size above 50MB.
Any help in this would be extremely helpful. And providing me code for this would be a great help.
Thanks in advance.
You can handle this with Audio Focus. Two or more Android apps can play audio to the same output stream simultaneously. The system mixes everything together. While this is technically impressive, it can be very aggravating to a user. To avoid every music app playing at the same time, Android introduces the idea of audio focus. Only one app can hold audio focus at a time.
When your app needs to output audio, it should request audio focus. When it has focus, it can play sound. However, after you acquire audio focus you may not be able to keep it until you’re done playing. Another app can request focus, which preempts your hold on audio focus. If that happens your app should pause playing or lower its volume to let users hear the new audio source more easily.
Beginning with Android 8.0 (API level 26), when you call requestAudioFocus() you must supply an AudioFocusRequest parameter. To release audio focus, call the method abandonAudioFocusRequest() which also takes an AudioFocusRequest as its argument. The same AudioFocusRequest instance should be used when requesting and abandoning focus.
To create an AudioFocusRequest, use an AudioFocusRequest.Builder. Since a focus request must always specify the type of the request, the type is included in the constructor for the builder. Use the builder's methods to set the other fields of the request.
The following example shows how to use an AudioFocusRequest.Builder to build an AudioFocusRequest and request and abandon audio focus:
audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
playbackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(playbackAttributes)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(afChangeListener, handler)
.build();
mediaPlayer = new MediaPlayer();
final Object focusLock = new Object();
boolean playbackDelayed = false;
boolean playbackNowAuthorized = false;
// ...
int res = audioManager.requestAudioFocus(focusRequest);
synchronized(focusLock) {
if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
playbackNowAuthorized = false;
} else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
playbackNowAuthorized = true;
playbackNow();
} else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
playbackDelayed = true;
playbackNowAuthorized = false;
}
}
// ...
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (playbackDelayed || resumeOnFocusGain) {
synchronized(focusLock) {
playbackDelayed = false;
resumeOnFocusGain = false;
}
playbackNow();
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
synchronized(focusLock) {
resumeOnFocusGain = false;
playbackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
synchronized(focusLock) {
resumeOnFocusGain = true;
playbackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// ... pausing or ducking depends on your app
break;
}
}
}
Hope this helps! Also you can check Android's official documentation. If this doesn't help, you can check this site and this site for more documentation.
To play audio: Audio Track reference
To play video: Media Player reference
And now you could start on the main thread by showing in a Video View the video you want, and when is the time to play the sound you start playing the Audio Track. The tricky part will be to syncronize the audio with the video

MediaPlayer.prepare is throwing an IllegalStateException when playing m4a file

I have a list of songs that I'm streaming using the MediaPlayer. Some of the songs consistently work and others consistently do not work. I can't see a difference between these files, and they seem to play fine in itunes and such.
When the songs fail it is throwing an IllegalStateException on the mediaPlayer.prepare() line. The IllegalStateException that is thrown has no useful info in it, (detailMessage is null, stackState is null)
Here is my code
try {
mediaPlayer.setDataSource(media.url);
setPlayerState(PlayerState.PREPARING);
mediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "bad stream");
}
Here is a url to the file that does NOT work:
skdy.bryceb.dev.mediarain.com/song.m4a
Here is one that DOES work:
skdy.bryceb.dev.mediarain.com/song2.m4a
Any ideas why this works on some songs and fails on others?
Thanks MisterSquonk I'm sure that way would work.
In my particular case after beating my head against the wall for a while I realized that on some songs, I was getting to the buffered amount before the player state was getting set to prepared. So I added a check to make sure that the MediaPlayer was in the "PREPARED" state and then it worked great:
// Media prepared listener
mediaPlayer.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
setPlayerState(PlayerState.PREPARED);
}
});
// Media buffer listener
mediaPlayer.setOnBufferingUpdateListener(
new MediaPlayer.OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// Sometimes the song will finish playing before the 100% loaded in has been
// dispatched, which result in the song playing again, so check to see if the
// song has completed first
if(getPlayerState() == PlayerState.COMPLETED)
return;
if(getPlayerState() == PlayerState.PAUSED)
return;
// If the music isn't already playing, and the buffer has been reached
if(!mediaPlayer.isPlaying() && percent > PERCENT_BUFFER) {
if(getPlayerState() == PlayerState.PREPARED)
{
mediaPlayer.start();
setPlayerState(PlayerState.PLAYING);
}
//if it isn't prepared, then we'll wait till the next buffering
//update
return;
}
}
});
OK, I hacked together a minimal Mediaplayer implementation in a 'sandbox' app/activity I always keep spare for testing.
I might be wrong but if you're streaming these songs over the net, you'll need to prefix the url with http://.
I tried the urls with Winamp and Chrome verbatim (no protocol prefix string) and they worked fine although it's likely both of those applications will use some form of intelligence to work out how to connect/stream.
If I tried that in my mediaPlayer code, I get the same exception as you but if I prefix the urls with http:// the songs play fine.
Example...
// Activity scope
Button button;
CheckBox checkBox;
String url = "";
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//button declared in my activity
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
if (!checkBox.isChecked())
url = getString(R.string.url_song1);
else
url = getString(R.string.url_song2);
mediaPlayer = new MediaPlayer();
}
#Override
public void onClick(View arg0) {
try {
Log.i(TAG, "onClick() entered...");
mediaPlayer.setDataSource(url);
Log.i(TAG, "Preparing mediaplayer...");
mediaPlayer.prepare();
Log.i(TAG, "Starting mediaplayer...");
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "bad stream");
}
}
If I copy the songs to my SD card both play fine and as long as the internet url strings have an 'http://' prefix then they also work.

VideoView not playing on some devices

I have fragment which contains CameraPreview as background and in one of the corners i have 100x100dp video view which must play mp4 h.264 format video,
but for some reason some of the devices play other won't the problem that no error thrown it just not showing .
This is the function to prepare the video.
private void setupVideoView(){
String path = "android.resource://"+ getActivity().getPackageName()+"/"+R.raw.model_2;
Uri uri = Uri.parse(path);
mVideoView.setVideoURI(uri);
mVideoView.seekTo(1);
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setLooping(true);
}
});
}
then after couple seconds i need to start the video, then i call
if(mVideoView != null){
mVideoView.start();
}
i had read about which codecs and format android accept and my video is perfect suit this requirements as i said above its mp4 h.264 format , any idea?

Categories

Resources