I was using MediaPlayer to play sounds in my App but from Its start to freeze the App:
Thats the code where I call create method. I moved the code inside an AsyncTask class :
public class BackgroundSound extends AsyncTask<Integer,Void,Void> {
MediaPlayer mpB;
MediaPlayer mpG;
Context ctx;
BackgroundSound(Context appctx)
{
ctx = appctx;
}
#Override
protected Void doInBackground(Integer... Params) {
switch (Params[0]){
case 0:
mpB = MediaPlayer.create(ctx, R.raw.sonidoemocion5sec);
mpB.setLooping(true);
mpB.setVolume(0.75f, 0.75f);
mpB.start();
break;
case 1:
if (mpG != null)
{
mpG.release();
mpG = null;
}
mpG = MediaPlayer.create(ctx, R.raw.ganador);
mpG.setVolume(1, 1);
mpG.start();
break;
case 2:
if (mpG != null){
mpG.release();
mpG = null;
}
mpG = MediaPlayer.create(ctx, R.raw.perder);
mpG.setVolume(1, 1);
mpG.start();
break;
}
return null;
}
}
Debuging I find that the freeze (app still running but dont make anything) occurred in the new line inside the method create from MediaPlayer.java file::
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder,
AudioAttributes audioAttributes, int audioSessionId) {
try {
MediaPlayer mp = new MediaPlayer();
I don't understand what's going on. Any tips?
The warn & Error Log exits:
Instead of using MediaPlayer.create(), use mp.setDataSource() method so that you can call mp.prepareAsync() and then set listener to listen for its completion like this:
mp.setDataSource(this, audioUri);
mp.prepareAsync();
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
Now for this audioUri object of Uri, you can set it to your audio files in the raw folder by having this line of code in your project:
audioUri = Uri.parse("android.resource://com.yourpackagename/" + R.raw.your_audiofile_name);
This method prepares the mp asynchronously and doesn't block the UI
There are two possible solutions for this issue, but it is not sure that it will work properly as I have not tested it.
Solution 1.
Replace below line:
audiojuego = MediaPlayer.create(this, R.raw.sonidoemocion);
with:
audiojuego = MediaPlayer.create(getApplicationContext(), R.raw.sonidoemocion);
//As you are calling from doInBackground() method, this will not work properly.
Solution 2.
Initialize media player by your own way instead of default.
Uri url=Uri.parse("android.resource://"+getPackageName()+"/raw/sonidoemocion");
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
Related
I have a Service that starts a thread, where I need to create a MediaPlayer:
Inside onStartCommand I call the main function that runs a thread.
public int onStartCommand(Context context, Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
doTask(context);
return START_STICKY;
}
void doTask(Context context) {
isActive = true;
thread = new Thread(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void run() {
try {
threadLoop(context);
}
catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
Log.e(TAG, "Thread started");
}
After this, inside threadLoop I am trying to create a MediaPlayer
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer = MediaPlayer.create(context, AudioData);
but I can't do anything with the 1st context parameter. I tried to send context and get the base one, but it doesn't work.
Maybe I should use another service for MediaPlayer?
Thank you in advance
Update
Error:
Cannot resolve method 'create(android.content.Context, short[])'.
You're passing in the wrong data to the second parameter. The first parameter is fine. The second is a resource id or a Uri, not a short[]. If the short array is supposed to be audio data (like the raw .wav data), write it to a file and pass it the URI of that file.
Also, passing context to a Thread like that is dangerous and can lead to memory leaks. You need to make sure the thread is ended when the service is ended to prevent it.
Your code should be like this
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer = MediaPlayer.create(this, uri);
Basically what I want is to allow the user to select a audio file from their device and once they do, this activity starts and the music/audio file will be played. For that I've used included an intent-filter in my Android Manifest File, and its working fine, there are no errors.
The problem is when I call mediaPlayer.start() I get a Null Pointer Exception. From what I've read so far, this happens because MediaPlayer fails to create a object or something... the MediaPlayer.cretae() returns null.
The following is the whole code for this Activity:
public class IntentPlayerActivity extends AppCompatActivity {
TextView song_name,artist_name;
ImageView playPauseBtn;
SeekBar seekBar;
static Uri uri;
static MediaPlayer mediaPlayer = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_player);
initViews();
Intent intent = getIntent();
if (intent.getAction().equals(Intent.ACTION_VIEW)){
Log.d("Intent Player_Activity:", " File Path: "+ intent.getData().getPath());
playPauseBtn.setImageResource(R.drawable.ic_pause_circle_outline);
uri = Uri.parse(intent.getData().getPath());
Log.d("Intent Player_Activity:", " URI: "+uri.toString());
if (mediaPlayer != null){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
mediaPlayer.start();
}else {
mediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
mediaPlayer.start();
}
}
}
private void initViews() {
song_name = findViewById(R.id.song_name);
artist_name = findViewById(R.id.song_artist);
playPauseBtn = findViewById(R.id.play_pause);
seekBar = findViewById(R.id.seekBar);
}
}
I'm hopping someone could explain what MediaPlayer.create() dose and what could be causing it to fail, for my case I don't believe the audio file is an invalid format or the specified media file cannot be found. I think its something else.
Delete:
uri = Uri.parse(intent.getData().getPath());
Instead, pass intent.getData() to MediaPlayer.create():
mediaPlayer = MediaPlayer.create(getApplicationContext(),intent.getData());
I am trying to play an audio file in Eclipse using MediaPlayer in Android programming.
I need to run the audio file (.wav or .mp3) which is saved on computer hard-drive. I have tried many things. I also tried copying the file in res folder of my project, but nothing worked. Below is my code.
As you can see I have tried many ways and commented some. I was first getting IOException earlier. But after using MediaPlayer.create(), I am getting IllegalStateException.
Any help would be very appreciated.
public void playSound(MainActivity mainActivity){
System.out.println("in playsound");
MediaPlayer mp = null;
FileInputStream fis = null;
try {
//fis = new FileInputStream("C:\\Users\\Anupam-PC\\Downloads\\trailsoundfilerecordings\\jagmeet.wav");
//mp.setDataSource(fis.getFD());
System.out.println("inside try");
//mp.setDataSource("/res/raw/hai.wav");
//mp.setDataSource("C:\\Users\\Anupam-PC\\Downloads\\trailsoundfilerecordings\\jagmeet.wav");
//mp.setDataSource("android.resource://com.example.texttospeech/agreji.mp3");
//mp.setDataSource("agreji.mp3");
mp = MediaPlayer.create(mainActivity, R.raw.hai);
System.out.println("after DS");
mp.prepare();
System.out.println("after prepare");
mp.start();
// fis.close();
} catch (Exception e) {
System.out.println(e);
} finally{
try{
fis.close();
} catch (Exception e){
}
}
You don't need to implement mp.prepare();, you have create(/**/)
This is my example that works like a charm:
class Vulcan implements MediaPlayer.OnPreparedListener{
MediaPlayer mediaPlayer = null;
...
boolean isPrepearedToPlayAudio = false;
mediaPlayer=MediaPlayer.create(context,R.raw.mini_vulcan_gun_1);
mediaPlayer.setOnPreparedListener(this);
public void stop(){
mediaPlayer.pause();
}
public void start(){
if(isPrepearedToPlayAudio){
mediaPlayer.start();
mediaPlayer.setLooping( true );
}
}
#Override
public void onPrepared(MediaPlayer mp) {
isPrepearedToPlayAudio = true;
}
Your invocation of MediaPlayer.create(...) already calls prepare(), and multiple calls to prepare() will cause an ISE. All you need to do is remove:
mp.prepare();
Javadoc:
Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.
When done with the MediaPlayer, you should call release(), to free the resources. If not released, too many MediaPlayer instances will result in an exception.
I am trying to play a few music (wav format) files based on button clicks. I am unable to get MediaPlayer to work properly. Every time I try to instantiate an object of MediaPlayer class, it fails on create(). Before I post the code, here is a run-through of what I am doing:
1. A layout file that contains 2 buttons.
2. Those buttons are read and onClickListeners defined for them.
3. Depending on the button clicked, a function called playAudioFile(View) called which creates the MediaPlayer instance and plays the file. The code for playAudioFile(View) is as follows:
public void playAudioFile(View v) {
/*Steps:
* 1. Take in id of the button.
* 2. Using id, identify what file needs to be played.
* 3. Play file.
*/
String path_to_file = null; //this is the path to the file.
if(b01.getId() == ((Button)v).getId()) {
Log.v(this.toString(), "Button 01 pressed.");
path_to_file = "/sdcard/audio/temp1.wav";
} else if(b02.getId() == ((Button)v).getId()) {
Log.v(this.toString(), "Button02 pressed.");
path_to_file = "/sdcard/audio/temp2.wav";
}
path_to_file = "file://" + path_to_file;
Uri streamUri = Uri.parse(path_to_file);
Log.v(this.toString(), "Path of file = " + path_to_file);
MediaPlayer mp = MediaPlayer.create(this, streamUri);
if(mp == null) {
Log.v(this.toString(), "Create() on MediaPlayer failed.");
}
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
try {
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
Log.v(this.toString(), "Illegal state exception thrown in start.");
}
}
});
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
I have gone through a lot of posts here on stackoverflow that detail solutions to the above problem. I am encountering this problem after having incorporated all the suggestions made therein. Any help is most welcome.
Thanks,
Sriram
I dont understand why you are trying to do
MediaPlayer mp = MediaPlayer.create(this, streamUri);
This is my implementation of my Player, Hope this will help you in some way:
MediaPlayer mp = new MediaPlayer();
setContentView(R.layout.player);
Intent intent = getIntent();
String path = "";
System.out.println("My Scheme : "+intent.getData().toString().substring(8));
if (intent.getData().getScheme().equals("video")) {
path = intent.getData().toString().substring(8);
System.out.println("Path : "+path);
if(path.endsWith(".mp3")) {
setContentView(R.layout.musicplayer);
setContentView(R.layout.controls);
Log.e("MusicPlayer", "Playing: " + path);
try {
Notification notification = new Notification(
R.drawable.playbackstart, path, System.currentTimeMillis());
nm.notify(NOTIFY_ID, notification);
mp.reset();
mp.setDataSource(path);
mp.prepare();
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
System.out.println("Hi i am at the End");
}
});
}catch {expression}
If I'm not wrong, you can't use onPrepare because mp.prepare() is called inside MediaPlayer.create(). The simpliest code can be something like this:
MediaPlayer mp = MediaPlayer.create(this, streamUri);
mp.start();
If you want something more elaborated, you can try this:
MediaPlayer mp = MediaPlayer.create(this, streamUri);
if(mp == null) {
Log.v(this.toString(), "Create() on MediaPlayer failed.");
} else {
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//here you should call the methods to release memory
mp.stop();
mp.release();
}
});
mp.start();
}
Tell me if it helped you.
PD: Is better if you use a device for testing rather than a simulator. Some classes don't work properly there (MediaPlayer can't reproduce video in simulators) and I don't remember if it supports audio.
As far as I understand your problem: You are calling the MediaPlayer.create(...) method, and it returns null, meaning the creation of a MediaPlayer instance failed. According to the accepted answer of this post MediaPlayer.create() always returns null it is due to a corrupted audio file.
I also have an issue, where the sound gets played but on rare occasions the create() method also returns null. I use sounds in a turn based game, after each turn a sound is played. I always call the create method, start the player and release it when it's done. That happens every turn and like once in 300 turns the create method returns null... So in my case it must be something else. In yours it could probably have something to do with the corruption of the mp3 file.
I have a small (200kb) mp3 in the res/raw folder of my android app. I am trying to run it in an emulator from Eclipse. It is recognized as a resource in the R file but when I try to prepare/start, my activity crashes! Was there something else I needed to change, perhaps in the manifest?
MediaPlayer mPlayer = MediaPlayer.create(FakeCallScreen.this, R.raw.mysoundfile);
try {
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
// handle this later
}
When starting the activity i.e on onCreate put the following code.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MediaPlayer mPlayer = MediaPlayer.create(FakeCallScreen.this, R.raw.mysoundfile);
mPlayer.start();
}
When stopping the activity i.e on onDestroy put the following code.
public void onDestroy() {
mPlayer.stop();
super.onDestroy();
}
Hope it helps :)
You'll likely prefer to use the SoundPool class. It reduces latency when it's time to play the sound, and offers other niceties like being able to prioritise sounds when there are too many to play at once.
From the docs:
A SoundPool is a collection of samples that can be loaded into memory from a resource inside the APK or from a file in the file system. The SoundPool library uses the MediaPlayer service to decode the audio into a raw 16-bit PCM mono or stereo stream. This allows applications to ship with compressed streams without having to suffer the CPU load and latency of decompressing during playback.
For example:
/**
* How many sounds can be played at once.
*/
private static final int MAX_SOUND_POOL_STREAMS = 4;
/**
* Modify this as part of your own priority scheme. Higher numbers mean higher
* priority. If you don't care, it's okay to use the same priority for every
* sound.
*/
private static final int NORMAL_PRIORITY = 10;
private int mySoundId;
#Override
public void setupContent() {
this.soundPool = new SoundPool(MAX_SOUND_POOL_STREAMS,
AudioManager.STREAM_MUSIC, 100);
this.mySoundId = this.soundPool.load(this.getApplicationContext(),
R.raw.mySound, 1);
}
#Override
private void playMySound() {
this.soundPool.play(this.mySoundId, 1, 1, NORMAL_PRIORITY, 0, 1);
}
this is a static method I use in my projects.
I add it to my Utils class:
public static void playSound(final Context context, final SoundType type)
{
new Thread(new Runnable()
{
#Override
public void run()
{
MediaPlayer mediaPlayer = new MediaPlayer();
int resId = -1;
switch (type)
{
case INCOMING_NOTIFICATION:
resId=R.raw.noti_sound;
break;
case SEND_BETTING_SLIP:
resId=R.raw.slip_sent;
break;
case TRIVIA_RIGHT_ANSWER:
resId=R.raw.game_bonus;
break;
case TRIVIA_WRONG_ANSWER:
resId=R.raw.whistle_referee_trivia_bad_answer;
break;
}
if (resId != -1)
{
mediaPlayer = MediaPlayer.create(context, resId);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(false);
mediaPlayer.start();
while (mediaPlayer.isPlaying() == true)
{
}
}
}
}).start();
}
}
now I defind an Enum (SoundType) and placed the mp3 files in raw folder under
res folder.