Starting media player in a thread problem - android

I'm trying to start a media player that streams from a website. Right now, when "start" is pressed the entire activity just freezes for anywhere from 5 to 20 seconds while the stream connects. I'm trying to get the "player.start();" call to run in a thread to free up the activity while the stream connects but it's not working. Anyone have any ideas?
private void startplayer() {
try {
stream_player = new MediaPlayer();
stream_player.setAudioStreamType(AudioManager.STREAM_MUSIC);
stream_player = MediaPlayer.create(this, Uri.parse("http://stream-address"));
Thread thread = new Thread(new Runnable() {
public void run() {
stream_player.start();
}
});
thread.start();
SetNotification(1, "live");
liveON = true;
} catch (Exception e) {
Log.e(getClass().getName(), "Error starting to stream audio.", e);
Toast.makeText(this, "Stream seems to be offline", Toast.LENGTH_LONG).show();
}
}

Move the whole method to a separate thread. The part that takes the most time is the MediaPlayer.create() part, since this a synchronous call, which returns when the media player is ready to play.
An alternative is not to use create, but use the other format used in here which sets a listener before the prepare method, and when the listener is called, the start method is called.

Related

How to stop worker thread in Android

I found and use some method bellow but it is not work for me:
myThread.stop() //it is not safe but I am tried that
myThread.interupt
Here is my program: I wanna play video using Videoview when video finish. If user no choose the next video in 120s then my app will finish.
My video view code:
Uri uri = Uri.parse(filePath);
videoView = findViewById(R.id.videoView);
videoView.setVideoURI(uri);
waitingThread w8 = new waitingThread();
//set params video before play
videoView.setOnPreparedListener(mediaPlayer -> {
PlaybackParams playbackParams = new PlaybackParams();
playbackParams.setSpeed(DeviceConfig.getInstance().getVideoPeed());// 1.25 1.5 2 2.5
mediaPlayer.setPlaybackParams(playbackParams);
// I am tryied using stop thread here
// w8.stop()
// or w8.interrupt();
videoView.start();
});
videoView.setOnErrorListener((mediaPlayer, i, i1) -> {
Log.d(TAG,"Video Error");
//send error message to server
return false;
});
//I call thread when video complete
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
**waiting();** -> w8.start //edited i start thread here
}
});
My thread waiting
private class waitingThread extends Thread{
public void run() {
try {
while (!isInterrupted()) {
timeCount ++;
Thread.sleep(1000);
Log.d(TAG, "Time count : " + timeCount);
if(timeCount == 120){
finish();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//i am try to using this funtion but still not work too.
public void stopping(){
Thread.currentThread().interrupt();
// timeCount = 0;
// Log.d(TAG, "Stopping, reset time :" + timeCount);
}
}
Brief my idea: When video start play, thread waiting will be stopped. When video finish program will waiting a time if no video chose in time to wait program will finish, if any video chose then thread w8 stop.
My problem: when I choose the next video, my thread "w8" still keep running. That is make my app finished while video playing
Plz help me how to fix that problem or any same idea to work are appreciated
You don't want to call interrupt on Thread.currentThread. Thread.currentThread is the thread currently running- it's the thread you're calling the function on. It's not the thread object you just created. Instead it would be this.interrupt(). Or just get rid of the function entirely and call interrupt directly.
Introducing your own boolean variable might help
class waitingThread extends Thread{
boolean stop;
public void run(){
while(!stop){
//your task
}
stop = false; //
}
public void stopping(){
stop= true;
}
}

Play music synchronous using 3 MediaPlayer Objects on Android/Eclipse

What i have:
I have implemented three MediaPlayer.Objects in my App.
All Three are created using a thread:
protected void onResume() {
// Threads
mTT1 = new TrackThread(this, R.raw.audiofile1, 1, mHandler);
mTT2 = new TrackThread(this, R.raw.audiofile2, 2, mHandler);
mTT3 = new TrackThread(this, R.raw.audiofile3, 3, mHandler);
// start thread
mTT1.start();
mTT2.start();
mTT3.start();
super.onResume();
}
"simplified" Code in the Thread for creating:
public class TrackThread extends Thread implements OnPreparedListener {
...
...
...
public void run() {
super.run();
try {
mMp.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getDeclaredLength());
mMp.prepare();
} catch (IllegalArgumentException | IllegalStateException
| IOException e) {
Log.e(TAG, "Unable to play audio queue do to exception: "
+ e.getMessage(), e);
}
}
As I read in several Tutorials the "prepare()" methode takes a little bit of time to finish. Therefore i implemented a "Waiting loop" which waits until all MPs are prepared and created.
When "prepare and create" are done i enable the Start button and i want to start all 3 Mediaplayers SIMULTANEOUSLY.
I again use a Thread for dooing so:
public void onClick(View v) {
// Button 1
if (mBtn.getId() == v.getId()) {
mTT1.startMusic();
mTT2.startMusic();
mTT3.startMusic();
}
Code in the thread:
public class TrackThread extends Thread implements OnPreparedListener {
...
...
...
// start
public void startMusic() {
if (mMp == null)
return;
mMp.start();
}
Please note that the code above is not the full code, but it should be enough to define my problem.
What i want, My problem:
All MPs should play their Music in Sync, unfortunately sometimes when i start the music, there is a time delay between them.
The MPs must start at the exact same time as the 3Audio-files must be played simultaneously (and exactly in sync)
What i have already tried:
+) using SoundPool: My Audio-files are to big(5Megabyte and larger) for SoundPool
+) seekTo(msec): i wanted to seek every MP to a Specific time: eg.: 0, but this did not solve the problem.
+) to reach more Programmers i also asked this question on: coderanch.com
I hope somebody can help me!
Thanks in advance
The bottleneck here will certainly be preparing the mediaplayers to play. The Android framework provides an asynchronous method to perform this loading, and so with a bit of synchronization code you should be able to get these audio sources to play at roughly the same time. To keep from sound artifacting, you'll want less than 10ms of latency.
Initialize an atomic counter, C, to the number of things to load.
Use the prepareAsync() functions within MediaPlayer to prepare all three. Immediately after calling prepareAsync, supply a listener using setOnPreparedListener(listener).
Inside this listener, decrement C and check the value. If the value is greater than 0, wait on an object using the java object .wait() function. If the value is equal to 0, call notifyAll() on the object to wake up all of the other mediaplayer prepared-listener callback threads.
public void startMediaPlayers(List<MediaPlayer> mediaPlayers) {
private AtomicInteger counter = new AtomicInteger(mediaPlayers.size());
Object barrier = new Object();
/* start off all media players */
for (MediaPlayer player : mediaPlayers) {
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mediaPlayer) {
int value = counter.decrementAndGet();
if (value == 0) {
// all media players are done loading.
// wake up all the ones that are asleep
barrier.notifyAll();
} else {
while (value > 0) {
try {
// wait for everyone else to load
barrier.wait();
} catch (InterruptedException e) {
// ignore
}
}
}
mediaPlayer.start();
callback.success(true);
}
player.prepareAsync();
}
}
As nobody could help me I found a solution on my own. MediaPlayer did not fulfill my requirements but Android JETPlayer in combination with JETCreator did.
CAUTION: Installing Python for using JETCreator is very tricky, therfore
follow this tutorial. And be careful with the versions of python and wxpython, not all versions support the JETCreator.
I used:
Python Version 2.5.4 (python-2.5.4.msi)
wxPython 2.8 (wxPython2.8-win32-unicode-2.8.7.1-py25.exe)
For those who do not know how to implement the Jetplayer watch this video
(at min.5 he starts with programming the Jetplayer).
Unfortunately I do not speak French so I just followed the code which worked for me.
Using Android JETCreator you can create your own JET Files and use them as your resource.
Useful links:
Demo data
Manual
Code/class

Media Player Class in Android the implementation scenario

for last three weeks I have worked on a Media Player in Android.I am trying to find a solution of how can I make my Media Player to change the song when it's already playing one.
Here is my Listener on the RecyclerView
musicList.addOnItemTouchListener(
new RecyclerItemClickListener(getApplicationContext(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, final int position) {
currentPosition = position;
if(!mediaPlayer.isPlaying()){
musicThread.start();
} else {
mediaPlayer.reset();
}
}
})
);
}
and my Thread is this:
final Thread musicThread = new Thread(new Runnable(){
#Override
public void run() {
try {
URL = getMusicURL(myDataset[currentPosition]);
try {
mediaPlayer.setDataSource(URL);
//mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.prepareAsync(); // prepare async to not block main thread
} catch (IOException e) {
e.printStackTrace();
Log.i("TEST","Eroare: "+e.getMessage());
}
} catch (StorageApiException e) {
e.printStackTrace();
Log.i("TEST","Eroare: "+e.getMessage());
}
}
});
I think you have a mess. First of all, you dont need a thread to play music, the own mediaplayer API does it for you when you call mediaPlayer.start(). However, you have to care about the time it takes to prepare the data source if you are for example streaming online music. For this, just use mediaPlayer.prepareAsync() and register a callback. When it has finished preparing, you can automatically start playing or do whatever you want.
If you want to change the data source, just follow the automaton map that you can find in MediaPlayer docs. Essentially, when the user selects another track, you register the call in your button listener, then reset the mediaPlayer, and recall all prepare, start... cycle again. By the way, it is advised to deploy all your mediaplayer code into a service so that it can keep playing even though the user has closed your activity.

Android MediaPlayer randomly skips playing some files

I've a multi-threaded app where main thread initiate two threads:
MakeRequest Thread
QueueListener Thread
MakeRequest thread after each second query a printer on LAN to request some data and perform some calculations on it and feed it to a Queue on which the second thread is listening. As soon as the data is available in the Queue, QueueListener thread dequeue a record from the Queue and initiate another thread i.e. MediaPlayer thread this thread is responsible for playing 7 to 8 files depending on the string received. For which I am using the following code.
MediaPlayer mp = MediaPlayer.create(context, Uri.fromFile(new File(q[voiceIndex])));
mp.setOnCompletionListener(mCompletionListener);
mp.setOnErrorListener(mErrorListener);
mp.start();
this code is in PlayMedia() method, and in OnCompletionListener, I've the following code:
OnCompletionListener mCompletionListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
//will be called when media player finished playing a file.
mp.release();
StartPlayingNextFile();
}
};
private void StartPlayingNextFile() {
voiceIndex++;
if (voiceIndex < q.length){
PlayMedia();
}else{
finishedPlaying = true;
}
}
When QueueListener Thread initiate MediaPlayer Thread I've used Join() on MediaPlayer thread in order not to dequeue another string from the queue and wait till the MediaPlayer finishes its business, otherwise I'll hear over lapping sounds.
Now, most of the time everything seems to be working fine but MediaPlayer sometime skips playing some files and thus MediaPlayer thread never terminates because OnCompletionListener never called and OnErrorListener never get called either, because of which Join() never releases, so I've to explicitly do it after a reasonable time has passed:
#Override
public void run() {
//record the start time
timeStart = new Date().getTime();
PlayMedia();
while (!finishedPlaying){
try {
//if a reasonable time has passed break the loop
long currentTime = (new Date().getTime() - timeStart);
long elapsedSeconds = TimeUnit.MILLISECONDS.toSeconds(currentTime);
if (elapsedSeconds > 15){
break;
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Log from LogCat can bee seen here where 5 files have been skipped between line 2 and 27 i.e.
Line 2:
01-21 01:20:18.474: V/MediaPlayerService(3240): Create new client(1854) from pid 15063, url=/mnt/sdcard/voicedata/200.wav, connId=1854
Line 27:
01-21 01:20:30.504: V/MediaPlayerService(3240): Create new client(1855) from pid 15063, url=/mnt/sdcard/voicedata/constants/bell.wav, connId=1855
files that have been skipped are:
/mnt/sdcard/voicedata/a.wav
/mnt/sdcard/voicedata/b.wav
/mnt/sdcard/voicedata/c.wav
/mnt/sdcard/voicedata/d.wav
/mnt/sdcard/voicedata/e.wav
and bell.wav is the very first file, that plays before all these files.
After rigorous testing I've found out that reducing the number of files actually improves the changes that MediaPlayer would not skip any file.

Service not able to run twice

I am making a music player with a service but when i click a song in the music list, the music starts with no errors, but if i go back to the list and click another i get Attempt to call getDuration without a valid mediaplayer error (-38, 0)
My onStart method in the service:
#Override
public void onStart(final Intent i, int startid) {
Log.d(TAG, "Start music");
re = 0;
songUrl = i.getData().toString();
streamMusic = new Thread() {
public void run() {
Looper.prepare();
try {
re = 1;
music.reset();
music.setDataSource(songUrl);
music.prepare();
this.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
};
streamMusic.start();
}
I start the service with startService(i); and I have set a music.setOnPreparedListener so nothing is runned to early.
How do I make it work?
Try calling reset() method before calling prepare again.
Also, if you are calling prepare() and not prepareAsync() I don't see why you need to use the prepared listener.

Categories

Resources