I have a MediaPlayerActivity with the following code:
This code basically tries to get a video stream from a http url and load it but for some reason it keeps crashing.
public class MediaPlayerActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.video_player);
SurfaceView v = (SurfaceView) findViewById(R.id.surface_video);
SurfaceHolder holder = v.getHolder();
holder.setFixedSize(400,300);
MediaPlayer mp = MediaPlayer.create(this, Uri.parse("http://stream-url.com/playlist.m3u8"));
mp.setDisplay(holder);
//mp.setAudioStreamType(2);
try {
//mp.prepare();
mp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
video_player.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SurfaceView android:id="#+id/surface_video"
android:layout_width="250px"
android:layout_height="250px">
</SurfaceView>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:padding="10dip"
>
</LinearLayout>
</LinearLayout>
When I go to this activity using the following code it crashes:
Intent myIntent = new Intent(HomeActivity.this, MediaPlayerActivity.class);
HomeActivity.this.startActivity(myIntent);
What am I doing wrong?
Without logs, two suggestions:
try implementing SurfaceHolder.Callback.surfaceCreated().
try using MediaPlayer.create() that accepts SurfaceHolder
Details of (1)
Maybe your surface is not yet created when you call start(). You should use MediaPlayer.setDisplay() and MediaPlayer.start() only after surface is created. To do this, you should add overrideSurfaceHolder.Callback.surfaceCreated()`. For example, your code could look like this.
public class MediaPlayerActivity extends Activity implements SurfaceHolder.Callback {
MediaPlayer mp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.video_player);
SurfaceView v = (SurfaceView) findViewById(R.id.surface_video);
SurfaceHolder holder = v.getHolder();
holder.setFixedSize(400,300);
holder.addCallback(this).
mp = MediaPlayer.create(this, Uri.parse("http://stream-url.com/playlist.m3u8"));
#Override
public void surfaceCreated(SurfaceHolder holder) {
mp.setDisplay(holder);
try {
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
Details of (2)
There seems to be other MediaPlayer.create() that accepts SurfaceHolder as one of the arguments - you could try it: http://developer.android.com/reference/android/media/MediaPlayer.html#create(android.content.Context, android.net.Uri, android.view.SurfaceHolder)
Related
I have an issue with Media player always stopping randomly after some few mins, most times, when the phone sleeps and you touch it again, the video hangs and stops playing.
I have tried many solutions here on stackoverflow, none worked. I'm almost pulling my hair out !!!
I've tried this answer
Android MediaPlayer stops playing after some time
MediaPlayer randomly stops on Android 4.4 (19)
How to prevent mediaplayer to stop when screen goes off?
and many more answers, they all didn't work
This is my code below
public class MainActivity {
MediaPlayer mp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mp = MediaPlayer.create(this, R.raw.my_webm_video);
mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
playVideo();
}
#Override
public void onResume() {
super.onResume();
mp = MediaPlayer.create(this, R.raw.my_webm_video);
mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
playVideo();
}
public void playVideo(){
SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = sv.getHolder();
holder.addCallback(new SurfaceHolder.Callback(){
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
#Override
public void surfaceCreated(SurfaceHolder holder) {
mp.setDisplay(holder);
mp.start();
mp.setLooping(true);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
}
This is my XML layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<SurfaceView
android:id="#+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
ok, so i finally solved the problem. Incase any one else run into this issue
in onCreate i checked if the video was already playing, to make sure it isn't called to re-play each time.
int firstPlayed = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mp = MediaPlayer.create(this, R.raw.my_webm_video);
mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
if(!mp.isPlaying()) {
firstPlayed = 1;
playVideo();
}
}
I checked in onResume incase the user navigates out of the activity and goes back, Which makes the video screen turn black.
public void onResume() {
super.onResume();
if(!mp.isPlaying() && firstPlayed == 0) {
mp = MediaPlayer.create(this, R.raw.my_webm_video);
mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
playVideo();
}
firstPlayed = 0;
}
And then i noticed that i needed a firstPlayed check to be sure.
I am playing an audio (mySound) as background music. On clicking a button, the background audio should stop and a different audio (mySound11) should start playing. After this audio gets done, the background music should automatically resume from where it had left. I have tried this code, but the background audio doesn't resume after mySound11 is over. Please help. Thanks in advance.
MainActivity.java
public class MainActivity extends ActionBarActivity {
MediaPlayer mySound;
MediaPlayer mySound11;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySound11 = MediaPlayer.create(this, R.raw.tiktik);
mySound = MediaPlayer.create(this, R.raw.jhakmaarke);
mySound.setLooping(true);
mySound.start();
}
public void playMusic (View view){
mySound.pause();
mySound11.start();
}
#Override
public void onResume() {
super.onResume();
mySound.start();
}
#Override
protected void onPause() {
super.onPause();
mySound.release();
mySound11.release();
finish();
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button Dabaa be"
android:onClick="playMusic"
android:id="#+id/button"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="72dp" />
I Solved your problem with the help of Thread.
I tested it working as you wished.
int mySound11Duration;
MediaPlayer mySound;
MediaPlayer mySound11;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySound11 = MediaPlayer.create(this, R.raw.tiktik);
mySound = MediaPlayer.create(this, R.raw.jhakmaarke);
mySound.setLooping(true);
mySound.start();
}
public void playMusic(View view) {
if (mySound.isPlaying()) { //check mysound is playing or not
mySound11Duration = mySound11.getDuration();
Thread thread=new Thread() {
#Override
public void run() {
try {
mySound.pause();
int mySoundPausePosition = mySound.getCurrentPosition();//get the time where the song is paused.
mySound11.start();
sleep(mySound11Duration);//sleep method causes the currently executing thread to sleep for specified number of time(miliseconds).
mySound.seekTo(mySoundPausePosition);
mySound.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
}
}
There are many controls to play youtube videos in eclipse like WebView, YouTubePlayerView, VideoView etc.
My doubt is can we play it using media player? Found that, url having extension like .mp4 can play using media player. But when tried with youtube video url it shows an error Start Called in state 0 .
if(isYTFlag){ //if youtube url
mediaPlayer.setDataSource(videoURL);
}
else{ //local mp4
afd = this.getResources().openRawResourceFd(Integer.parseInt(videoURL));
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
}
Please help to verify
Here is another working code
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_view);
VideoView videoView =(VideoView)findViewById(R.id.videoView);
MediaController mediaController= new MediaController(this);
mediaController.setAnchorView(videoView);
Uri uri=Uri.parse("rtsp://r2---sn-a5m7zu76.c.youtube.com/
Ck0LENy73wIaRAnTmlo5oUgpQhMYESARFEgGUg5yZWNvbW1lbmRhdGlvbnIhAWL2kyn64K6aQtkZVJdTxRoO88HsQjpE1a8d1GxQnGDmDA==/0/0/0/video.3gp");
videoView.setMediaController(mediaController);
videoView.setVideoURI(uri);
videoView.requestFocus();
videoView.start();}
activity_video_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<VideoView android:id="#+id/videoView"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
</LinearLayout>
YouTube Andorid Api
You can play the video using media player easily like below.
Player.java file
public class Player extends Activity implements SurfaceHolder.Callback,
OnPreparedListener {
private MediaPlayer mediaPlayer;
private SurfaceHolder vidHolder;
private SurfaceView vidSurface;
String vidAddress = "https://archive.org/download/ksnn_compilation_master_the_internet/ksnn_compilation_master_the_internet_512kb.mp4";
String videoSrc = "http://bffmedia.com/bigbunny.mp4";
String videoToPlay = "rtsp://v6.cache1.c.youtube.com/CjYLENy73wIaLQkDsLHya4-Z9hMYDSANFEIJbXYtZ29vZ2xlSARSBXdhdGNoYKX4k4uBjbOiUQw=/0/0/0/video.3gp";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.mediaplayer);
vidSurface = (SurfaceView) findViewById(R.id.surfView);
vidHolder = vidSurface.getHolder();
vidHolder.addCallback(this);
}
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mediaPlayer.start();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDisplay(vidHolder);
mediaPlayer.setDataSource(videoToPlay);
mediaPlayer.prepare();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
//mediaplayer.xml file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:paddingBottom="10dp" >
<SurfaceView
android:id="#+id/surfView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
//finally add internet permission in manifest.xml file
<uses-permission android:name="android.permission.INTERNET" />
Have you tried this?
btnPlay.setOnClickListener(new OnClickListener() {public void onClick(View v) {
startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse("https://www.youtube.com/watch?v=jHHn52KhBkQ")));
}}});
In this solution you can directly pass the youtube video url to the Intent which we want to play into media player.
For playing video try this link Playing(Streaming) video with MediaPlayer
Use your videoUrl instead of their 3gp video url.
I want to play a video with MediaPlayer in android, code is something like this:
MediaPlayer mMediaPlayer = new MediaPlayer()
mMediaPlayer.setDataSource(this.getContext, mUri, mHeaders)
I have a local file: /storage/emulated/0/Movies/test.mp4, how can I get the mUri of this file?
In fact, android.net.Uri have a method fromFile(File file), it returns a Uri like this: file:///storage/emulated/0/Movies/test.mp4. But this does work in setDataSource() method.
UPDATED:
I don't want to misleading someone in this problem.
In fact, Uri.parse("/storage/emulated/0/Movies/test.mp4") and Uri.parse("file:///storage/emulated/0/Movies/test.mp4") should be ok in my situation. But it is just my mp4 file's problem!
just change your file:/... to file:/// and it will work
Uri.parse(uri.toString().replace("file:/", "file:///"));
or simply if you have a file try
Uri.parse(String.valueOf(Uri.fromFile(myFile)));
Actually the thing is that the media player requires MRL followed by your path to file
EDIT
I have answered a question on how to initialise MediaPlayer using Uri here
Use the above MRL and initialise your player as suggested and enjoy your video :)
UPDATE:
I thought I should share part of my implementation so that it may help you out:
1st
Add below line to your manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2nd
Make your activity look like
public class MyActivity extends Activity implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener {
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private MediaPlayer mMediaPlayer;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setFormat(PixelFormat.UNKNOWN);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
String stringPath = "/storage/emulated/0/Movies/Lesson%201/30%20-%20Create%20Some%20Fake%20Data.mp4";
stringPath = android.net.Uri.parse("file://" + stringPath).getPath();
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setDataSource(stringPath);
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
}
and for testing your xml can be like
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SurfaceView
android:id="#+id/surfaceview"
android:layout_width="300dp"
android:layout_height="169dp"
/>
</LinearLayout>
Try This
String filePath = "file:///storage/emulated/0/Movies/test.mp4"
filePath.replace("file:///", "/"));
MediaPlayer player = MediaPlayer.create(this, Uri.parse(filePath));
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
I'm offering another answer to the original question, which may not be applicable to the specific problem as described by #roger later on. I have found that there is no need to further process/parse the media file path. Just use it directly. For example, I have a locally-stored media file on my Samsung Galaxy phone: "/storage/emulated/0/Samsung/Music/Over_the_Horizon.mp3"
. The following simple code works for playing the file:
String url = "/storage/emulated/0/Samsung/Music/Over_the_Horizon.mp3";
MediaPlayer mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(url);
mPlayer.prepare();
mPlayer.start();
(I have omitted try-catch blocks and other non-basic code). If SecurityException or IOException is issued while running the code, most likely a user permission needs to be added at the right place inside AndroidManifest.xml file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<application
</application>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>
I have a problem with playing video in mediaplayer. I have a sound but no video. I tried everything and can't find solve. Or maybe you know how to play sdp file in videoview? Here's the code:
public class TestStream1 extends Activity implements Callback{
MediaPlayer mMediaPlayer;
String SrcPath = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov";
private SurfaceView mPreview;
private SurfaceHolder holder;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPreview = (SurfaceView) findViewById(R.id.surface);
holder = mPreview.getHolder();
holder.addCallback(TestStream1.this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.setFixedSize(400,300);
mMediaPlayer = new MediaPlayer();
try{
mMediaPlayer.setDataSource(SrcPath);
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepare();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.start();
}catch(Exception e){
Toast .makeText( TestStream1.this, "Fail", Toast.LENGTH_LONG).show();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
EDIT: layout file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
</LinearLayout>
Some videos cannot be played in mediaplayer, if it doesn't have the codec for its a/v or it is too complex or badly interleaved (Look at Logcat for signs about some). Could be one or more reasons. To make sure the mediaplayer can play the type of video you are asking it to play, save a video file of the same a/v codec and extension to your sd card and then try to play it using the default media player.
Meanwile, try using a videoView to check the video can be played.Your code seems all right.
Try this code :
package a.b;
public class TestStream1 extends Activity implements Callback{
MediaPlayer mMediaPlayer;
String SrcPath = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov";
private SurfaceView mPreview;
private SurfaceHolder holder;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPreview = (SurfaceView) findViewById(R.id.surface);
holder = mPreview.getHolder();
holder.addCallback(TestStream1.this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.setFixedSize(400,300);
mMediaPlayer = new MediaPlayer();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try{
mMediaPlayer.setDisplay(holder);
mMediaPlayer.setDataSource(SrcPath);
mMediaPlayer.prepare();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.start();
}catch(Exception e){
Toast .makeText( TestStream1.this, "Fail", Toast.LENGTH_LONG).show();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mMediaPlayer.release();
}
}
SurfaceHolders are created ansynchronously, so we have to wait until the surface has been created and then assign the returned surface holder object .
And I am using the following layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<SurfaceView
android:id="#+id/surface"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
The above solution should work.
Note sure, but try setting the datasource like:
mMediaPlayer.setDataSource(this, SrcPath);