Sound not playing in Android version greater than 4.0 - android

I am using following code to play sound in my app. Everything worked fine before ICS. But on ICS and more recent versions no sound can be heard although there is no error appearing.
EDIT: Note, the following code is triggered by a broadcase receiver. BroadCast receiver invokes a async task. In the post process method of asycn task the following method is called.
This error happens only on specific mobile models (Eg nexus ) and on some models users are able to play sounds which comes with stock os but not their own sounds which they places in rigtones folder.
I am not able get whats the issues as it happens on specific handset
What could the error possibly be?
public static void playSound(final Context context, final int volume,
Uri uri, final int stream, int maxTime, int tickTime) {
//stopPlaying();
/*
if (stream < 0 || stream > 100) {
throw new IllegalArgumentException(
"volume must be between 0 and 100 .Current volume "
+ volume);
}*/
final AudioManager mAudioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
int deviceLocalVolume = getDeviceVolume(volume,
mAudioManager.getStreamMaxVolume(stream));
Log.d(TAG,
"device max volume = "
+ mAudioManager.getStreamMaxVolume(stream)
+ " for streamType " + stream);
Log.d(TAG, "playing sound " + uri.toString()
+ " with device local volume " + deviceLocalVolume);
final int oldVolume = mAudioManager.getStreamVolume(stream);
// set the volume to what we want it to be. In this case it's max volume
// for the alarm stream.
Log.d(Constants.APP_TAG, "setting device local volume to " + deviceLocalVolume);
mAudioManager.setStreamVolume(stream, deviceLocalVolume,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
final MediaPlayer mediaPlayer = new MediaPlayer();
golbalMMediaPlayer = mediaPlayer;
try {
final OnPreparedListener OnPreparedListener = new OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
Log.d(TAG, "onMediaPlayercompletion listener");
mp.start();
countDownTimer.start();
}
};
mediaPlayer.setDataSource(context.getApplicationContext(), uri);
mediaPlayer.setAudioStreamType(stream);
mediaPlayer.setLooping(false);
mediaPlayer.setOnPreparedListener(OnPreparedListener);
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Log.d(Constants.APP_TAG, "Entered onCompletion listener of mediaplayer");
mAudioManager.setStreamVolume(stream, oldVolume,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
try{
if(mediaPlayer != null && mediaPlayer.isPlaying()){
mediaPlayer.release();
}
}catch(Exception ex){
Log.e(Constants.APP_TAG, "error on oncompletion listener" ,ex);
}
}
});
CountDownTimer timer = new CountDownTimer(maxTime*1000, tickTime*1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.d(TAG, "tick while playing sound ");
}
#Override
public void onFinish() {
Log.d(TAG, "timer finished");
stopPlaying();
}
};
countDownTimer = timer;
mediaPlayer.prepareAsync();
} catch (Exception e) {
Log.e(TAG, "problem while playing sound", e);
} finally {
}
}
LOGS
:07-01 00:00:00.030: D/beephourly(9500): device max volume = 7 for streamType 5
07-01 00:00:00.030: D/beephourly(9500): playing sound content://media/internal/audio/media/166 with device local volume 7
07-01 00:00:00.030: D/beephourly(9500): setting device local volume to 7
07-01 00:00:00.080: D/beephourly(9500): vibrating with pattern = [J#428bae20
07-01 00:00:00.090: D/beephourly(9500): will show normal notification
07-01 00:00:00.100: D/beephourly(9500): notification is enabled
07-01 00:00:00.100: D/usersettings(9500): hr = 0
07-01 00:00:00.110: D/beephourly(9500): onMediaPlayercompletion listener
07-01 00:00:00.451: D/beephourly(9500): tick while playing sound
07-01 00:00:20.460: D/beephourly(9500): timer finished
07-01 00:00:20.460: D/beephourly(9500): got request to stop playing
07-01 00:00:20.460: D/beephourly(9500): cancelling countdowntimer
07-01 00:00:20.460: D/beephourly(9500): releasing mediaplayer now
This question is a follow up question to question which i asked previously:
sound not playing in android > icecream sandwich

You should be requesting audio focus, even for notifications. In your case it would look something like this:
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
//request a transient lock on the notification stream
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_NOTIFICATION,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// could not get audio focus.
}
I suspect there is some other app(s) running on the devices which are giving you problems which are requesting audio focus. If other apps request audio focus, and you do not, it is possible your app will not be played out to the final stream. Requesting focus yourself will ensure no other processes are interfering with your notification sound. Although this was introduced a while ago, newer versions of Android are much more sensitive to apps using this mechanism, especially from the background.
To be proper, when you're done with the notification, you can then release the focus:
audioManager.abandonAudioFocus(this);

Related

Load asset files inside background service

I am developing a widget that plays a random sound. My problem lies in getting the service I use to handle the MediaPlayer and play the sounds to load the sound files I have stored in my app's asset folder.
Instead of a SoundPool as in my application, I opted for a MediaPlayer since it has an onCompletionListener which allows me to stop the Service after the sound has been completely played. That way I hope to minimize the resource usage of the widget.
More precisely, in my code (checkout the [now outdated] commit on GitHub) I try to load a random sound with the MediaPlayer's create() convenience method using an Uri to file:///android_asset/pathToFile.
This however throws an IOException at runtime.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_PLAY_FART.equals(action)) {
Log.v(LOG_TAG, "Intent received");
String pathToFile = String.format(
Locale.US,
"fart%02d.ogg",
Utility.getIntBetween(1, 15)
);
MediaPlayer tempMediaPlayer = MediaPlayer.create(
this,
Uri.parse("file:///android_asset/"+pathToFile)
);
tempMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
stopSelf();
}
});
Log.v(LOG_TAG, "Start playing");
tempMediaPlayer.start();
}
}
return START_NOT_STICKY;
}
Is there an easy way (i. e., other than a Content Provider) to load those asset files from inside the Service?
[Edit, providing more information]
Apparently it is possible to access the asset files but the MediaPlayer cannot load them properly.
I modified the code to this:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_PLAY_FART.equals(action)) {
Log.v(LOG_TAG, "Intent received");
String pathToFile = String.format(
Locale.US,
"fart%02d.ogg",
Utility.getIntBetween(1, 15)
);
try {
AssetFileDescriptor assetFD = this.getAssets().openFd(pathToFile);
MediaPlayer tempMediaPlayer = new MediaPlayer();
tempMediaPlayer.setDataSource(assetFD.getFileDescriptor());
tempMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
stopSelf();
}
});
Log.v(LOG_TAG, "Start playing");
tempMediaPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "File "+pathToFile+" could not be loaded.", e);
}
}
}
The output I get is:
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/VolatileFartService﹕ Intent received
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/MediaPlayer﹕ constructor
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/MediaPlayer﹕ setListener
08-29 15:29:54.868 10191-10191/com.y0hy0h.furzknopf V/MediaPlayer﹕ setDataSource(51, 0, 576460752303423487)
08-29 15:29:54.898 10191-10191/com.y0hy0h.furzknopf E/MediaPlayer﹕ Unable to to create media player
08-29 15:29:54.908 10191-10191/com.y0hy0h.furzknopf E/VolatileFartService﹕ File fart07.ogg could not be loaded.
java.io.IOException: setDataSourceFD failed.: status=0x80000000
at android.media.MediaPlayer.setDataSource(Native Method)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1032)
at com.y0hy0h.furzknopf.widget.VolatileFartService.onStartCommand(VolatileFartService.java:39)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2524)
at android.app.ActivityThread.access$1900(ActivityThread.java:138)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1302)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4929)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at dalvik.system.NativeStart.main(Native Method)
Note that line 39 is
tempMediaPlayer.setDataSource(assetFD.getFileDescriptor());
Alternitavely, is there a way to pass the FileDescriptor or other object for the service to load?
Or might there be an even better way to handle the playback of possibly multiple sounds simultaneously than to put that functionality in a Service?
As an alternative to Want2bExpert's suggestion of moving the files into the res/raw folder, the asset files can be loaded "manually" into the MediaPlayer.
Apparently the assets are not stored as would be expected. Instead, the start position and length of the asset together with its (non Asset-)FileDescriptor needs to be passed on to the MediaPlayer.
The working code:
String pathToFile = String.format(
Locale.US,
"fart%02d.ogg",
Utility.getIntBetween(1, 15)
);
try {
AssetFileDescriptor assetFD = getAssets().openFd(pathToFile);
MediaPlayer tempMediaPlayer = new MediaPlayer();
tempMediaPlayer.setDataSource(
assetFD.getFileDescriptor(),
assetFD.getStartOffset(),
assetFD.getLength()
);
assetFD.close();
tempMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
stopSelf();
}
});
tempMediaPlayer.prepare();
Log.v(LOG_TAG, "Start playing");
tempMediaPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "File "+pathToFile+" could not be loaded.", e);
}
Try this;
Create a raw folder inside your resource dir e.g. res/raw
put the files to play in the raw folder
load the file using media player as below
MediaPlayer mediaPlayer = MediaPlayer.create(serviceClass.this, R.raw.sound_file_1);
mediaPlayer.start();
Read more;
http://developer.android.com/guide/topics/media/mediaplayer.html#mpandservices

MediaPlayer - Alarm is played in headphones AND on the phone

I create a MediaPlayer like in the appended code. Everything works fine, but I've one problem: whenever an alarm is played and I'm connected to headphones, the sound is played on the phone and in the headphones. I would like the phone to be quiet in such a situation.
Actually, if I use the same function to create another music player to play music and set the stream type to AudioManager.STREAM_MUSIC, everything works fine.
I'm getting this behaviour on an android 4.4.4 phone and I know, that this code worked as expected on my old phone... With android 4.3 I think...
int streamVolume = ((AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).getStreamVolume(AudioManager.STREAM_ALARM);
if (streamVolume != 0)
{
mAlarmPlayer = createMediaPlayerIfNeeded(mAlarmPlayer, true, true, false);
try
{
mAlarmPlayer.setDataSource(this, Uri.parse(sound));
mAlarmPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mAlarmPlayer.setVolume(streamVolume, streamVolume);
mAlarmPlayer.prepareAsync();
}
catch (IOException e)
{
Log.e("MusicService", "IOException playing alarm: " + e.getMessage());
e.printStackTrace();
}
}
And here is the create function:
private MediaPlayer createMediaPlayerIfNeeded(MediaPlayer player, boolean setListenerOnPrepared, boolean setListenerOnCompletion, boolean setListenerOnError)
{
if (player == null)
{
player = new MediaPlayer();
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
if (setListenerOnPrepared)
player.setOnPreparedListener(this);
if (setListenerOnCompletion)
player.setOnCompletionListener(this);
if (setListenerOnError)
player.setOnErrorListener(this);
}
else
player.reset();
return player;
}

Android MediaPlayer setNextMediaPlayer not working

My objective is to create a VideoView that can play videos in a pre-defined play list.
I'm trying to use MediaPlayer.setNextMediaPlayer(...) to allow a seamless transition between two videos. However, when the first video finishes playing, the 2nd video will not start automatically as it should according to the documentation.
Xamarin Android Code:
Queue<MediaPlayer> MediaPlayerList = null;
private void PlayVideo()
{
MediaPlayerList = new Queue<MediaPlayer>();
//Let's go ahead and create all media players
VideoView_CurrentVideoView = new VideoView(this);
VideoView_CurrentVideoView.Completion += mVideoView_Completion;
VideoView_CurrentVideoView.Prepared += mVideoView_Prepared;
//Let's prepare all MediaPlayer
for (int i = 0; i < VideoView_CurrentVideoChannel.VideoAssetList.Count; i++)
{
string filePath = FilePath[i];
if (i == 0)
{
VideoView_CurrentVideoView.SetVideoPath(filePath);
VideoContainer.AddView(VideoView_CurrentVideoView);
}
else
{
MediaPlayer mpNew = new MediaPlayer();
mpNew.SetDataSource(filePath);
MediaPlayerList.Enqueue(mpNew);
}
}
VideoView_CurrentVideoView.Start();
}
void mVideoView_Completion(object sender, EventArgs e)
{
MediaPlayer mp = (MediaPlayer)sender;
mp.Release();
}
void mVideoView_Prepared(object sender, EventArgs e)
{
MediaPlayer mp = (MediaPlayer)sender;
//Take the next available MediaPlayer from the queue
MediaPlayer nextMediaPlayer = MediaPlayerList.Dequeue();
//Put the current MediaPlayer at the end of the queue
MediaPlayerList.Enqueue(mp);
nextMediaPlayer.Prepare();
mp.SetNextMediaPlayer(nextMediaPlayer);
}
Any help or suggestions will be greatly appreciated. This is coded in Xamarin Android.
Update #1: After moving the .Prepare() away from Prepared() event
Queue<string> VideoListQueue = null;
MediaPlayer NextMediaPlayer = null;
private void PlayVideo()
{
string filePath = FilePath[0];
//Create video view
if (VideoContainer.ChildCount == 0)
{
//setup the videoview container
VideoView_CurrentVideoView = new VideoView(this);
VideoView_CurrentVideoView.Info += VideoView_CurrentVideoView_Info;
VideoView_CurrentVideoView.Error += VideoView_CurrentVideoView_Error;
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
param.LeftMargin = 0;
param.RightMargin = 0;
param.BottomMargin = 0;
param.TopMargin = 0;
VideoView_CurrentVideoView.LayoutParameters = param;
VideoView_CurrentVideoView.LayoutParameters.Width = ViewGroup.LayoutParams.FillParent;
VideoView_CurrentVideoView.LayoutParameters.Height = ViewGroup.LayoutParams.FillParent;
VideoView_CurrentVideoView.Completion += VideoView_CurrentVideoView_Completion;
VideoView_CurrentVideoView.Prepared += VideoView_CurrentVideoView_Prepared;
VideoContainer.AddView(VideoView_CurrentVideoView);
}
VideoView_CurrentVideoView.SetVideoPath(filePath);
VideoView_CurrentVideoView.SeekTo(0);
VideoView_CurrentVideoView.Start();
}
void VideoView_CurrentVideoView_Prepared(object sender, EventArgs e)
{
//Do nothing at this moment
MediaPlayer mp = (MediaPlayer)sender;
}
void VideoView_CurrentVideoView_Completion(object sender, EventArgs e)
{
//GC the finished MediaPlayer
MediaPlayer mp = (MediaPlayer)sender;
mp.Reset();
mp.Release();
mp = null;
//Preparing the next MediaPlayer
MediaPlayer currentPlayer = NextMediaPlayer;
NextMediaPlayer = SetupNextMediaPlayer();
currentPlayer.SetNextMediaPlayer(NextMediaPlayer);
}
MediaPlayer SetupNextMediaPlayer()
{
MediaPlayer mp = new MediaPlayer();
//When the video start playing, let's get ready for next one
string sourceURL = VideoListQueue.Dequeue();
VideoListQueue.Enqueue(sourceURL);
string filePath = sourceURL;
mp = new MediaPlayer();
mp.Info += VideoView_CurrentVideoView_Info;
mp.Completion += VideoView_CurrentVideoView_Completion;
mp.Prepared += VideoView_CurrentVideoView_Prepared;
mp.SetDataSource(filePath);
mp.Prepare();
//Fire back the created MediaPlayer object to the caller
return mp;
}
void VideoView_CurrentVideoView_Info(object sender, MediaPlayer.InfoEventArgs e)
{
Console.WriteLine("What = " + e.What);
switch (e.What)
{
case MediaInfo.VideoRenderingStart:
{
//This is only happening on video first started
NextMediaPlayer = SetupNextMediaPlayer();
e.Mp.SetNextMediaPlayer(NextMediaPlayer);
break;
}
}
}
void VideoView_CurrentVideoView_Error(object sender, MediaPlayer.ErrorEventArgs e)
{
e.Handled = true;
}
At this moment, the media player will begin playing the 2nd video once the first one is done. However, the 2nd video only have sound and no video showing.
Anyone know what I did wrong? I have a feeling that it has to do something with the MediaPlayer not attached to the SurfaceView. However, I created the view using VideoView, how can I get the Surface from VideoView?
Regarding playing 2nd video only with sound: try to implement OnCompletionListener listener for each MediaPlayer with this:
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.setDisplay(null); //for current mediaPlayer
nextMediaPlayer.setDisplay(getHolder()); //for next video
}
});
I can't say that is is gapless, but somehow it works. To archive this I don't use standard VideoView, but custom View, that extends from SurfaceView.
what if you prepare and play the next mediaplayer on .Completion event? have you try it? although it may have a small delay
After many years of testing, this problem does not happen on all hardware. For example, I run the same APK on Nexus7, it appears to be seamless and everything is working. In contrast, if I run it on Amlogic media player board, it will render the above-described problem.
I decided to close this post off with a conclusion that it is something to do with the hardware. I know someone overcome this limitation by run everything in OpenGL, but that is completely a separate beast to deal with.
Conclusion
If you are having a similar problem as described above, there's nothing much you can do as it is heavily dependent on the hardware.

Strange flow for seekBar on Android MediaPlayer

I use MediaPlayer for playing a single MP3 song from network. Data source is the file downloaded from network. This files comes in chuncks.
Let's assume we have following playing state.
Song duration: 4:00
Current chunck loaded in player: 1:00
Let's say I want to skip some part of a song and seek forward. I do it with MediaPlayer.seekTo() method. If I seek to position (1:40) it is not performed correctly, seek bar goes at start position (00:00) and the playerr stops.
public static void seekTo(int progress) {
try {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(sFilePath);
mp.prepare();
int offset = (progress * mp.getDuration()) / 100;
if (sCompleted)
return;
sLastSeek = offset;
if (offset > sMediaPlayer.getDuration()) {
sMediaPlayer.reset();
sMediaPlayer.setDataSource(sFilePath);
sMediaPlayer.prepareAsync();
} else {
sMediaPlayer.seekTo(offset);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}

progressive video download using android media player

I'm working on Video streaming over Delay-Tolerant Networks using android mobiles. For that im trying to implement progressive video download based on the tutorial given by pocket journey
http://blog.infidian.com/2008/04/04/tutorial-custom-media-streaming-for-androids-mediaplayer/
While creating a new media player the prepareAsync function is blocking the video display, making streaming unbearable. Is there a way to display something while the media player is prepared?
I'm using SurfaceView and SUrfaceHolder to display the video as suggested in the API media demos.
private MediaPlayer createMediaPlayer(File mediaFile)
throws IOException {
MediaPlayer mPlayer = new MediaPlayer();
mPlayer.setOnErrorListener(
new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e(TAG, "Error in MediaPlayer: (" + what +") with extra (" +extra +")" );
return true;
}
});
// It appears that for security/permission reasons, it is better to pass a FileDescriptor rather than a direct path to the File.
// Also I have seen errors such as "PVMFErrNotSupported" and "Prepare failed.: status=0x1" if a file path String is passed to
// setDataSource(). So unless otherwise noted, we use a FileDescriptor here.
FileInputStream fis = new FileInputStream(mediaFile);
mPlayer.setDataSource(fis.getFD());
mPlayer.setDisplay(holder);
mPlayer.prepareAsync();
return mPlayer;
}
/**
* Transfer buffered data to the MediaPlayer.
* NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so
* this method should always be called using a Handler.
*/
private void transferBufferToMediaPlayer() {
try {
// First determine if we need to restart the player after transferring data...e.g. perhaps the user pressed pause
final boolean wasPlaying = mediaPlayer.isPlaying();
final int curPosition = mediaPlayer.getCurrentPosition();
Log.e(TAG, "Current position: "+curPosition);
final MediaPlayer temp = mediaPlayer;
// Copy the currently downloaded content to a new buffered File. Store the old File for deleting later.
File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".dat");
File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
// This may be the last buffered File so ask that it be delete on exit. If it's already deleted, then this won't mean anything. If you want to
// keep and track fully downloaded files for later use, write caching code and please send me a copy.
bufferedFile.deleteOnExit();
moveFile(downloadingMediaFile,bufferedFile);
// Pause the current player now as we are about to create and start a new one. So far (Android v1.5),
// this always happens so quickly that the user never realized we've stopped the player and started a new one
if(wasPlaying){
Log.e(TAG, "mediaPlayer paused");
mediaPlayer.pause();
}
//mediaPlayer.release();
// Create a new MediaPlayer rather than try to re-prepare the prior one.
mediaPlayer = createMediaPlayer(bufferedFile);
mediaPlayer.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mPlayer) {
// TODO Auto-generated method stub
mediaPlayer.seekTo(curPosition);
// Restart if at end of prior buffered content or mediaPlayer was previously playing.
// NOTE: We test for < 1second of data because the media player can stop when there is still
// a few milliseconds of data left to play
int mediaLength = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition();
boolean atEndOfFile = mediaLength >= 1000;
Log.e(TAG, "MediaLen:"+mediaLength);
if (wasPlaying || atEndOfFile){
Log.e(TAG, "starting new player");
temp.release();
mediaPlayer.start();
}
}
});
// Lastly delete the previously playing buffered File as it's no longer needed.
oldBufferedFile.delete();
}catch (Exception e) {
Log.e(TAG, "Error updating to newly loaded content.", e);
}
}
Consider using exoplayer
http://developer.android.com/guide/topics/media/exoplayer.html
it was built with streaming in mind from the docs:
ExoPlayer supports features not currently provided by MediaPlayer, including Dynamic adaptive streaming over HTTP (DASH), SmoothStreaming, and persistent caching. ExoPlayer can be extended to handle additional media formats, and because you include it as part of your app code, you can update it along with your app.

Categories

Resources