Media Player Class in Android the implementation scenario - android

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.

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

continue playing streaming audio when app is in the background in android

im building a app to stream live radio over wifi. The problem im having is how to i keep the app playing when the user minimizes the app?
private void initializeMediaPlayer() {
player = new MediaPlayer();
try {
player.setDataSource("url");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
player.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// playSeekBar.setSecondaryProgress(percent);
Log.i("Buffering", "" + percent);
}
});
}
You need to look into Services. They will let you do things in the background when the app minimizes.
When your app minimizes, you make an Intent that describes to your Service what is to be streamed and from what time. The Service will then construct a MediaPlayer and continue streaming. Also, a good idea would be to have a Notification that will let the user end this Service without opening the app.
One more condition is when the user maximizes the app after the Service has been playing for some time. In this case, you need a persistence mechanism to keep track. Like SharedPreferences or SQLite.
Documentation: http://developer.android.com/guide/components/services.html
You have to implement your mediaplayer as a service as an Activity will be in onstop state when minimized.
public class MyMediaPlayerService extends Service implements MediaPlayer.OnPreparedListener,MediaPlayer.OnCompletionListener,AudioManager.OnAudioFocusChangeListener {
static MediaPlayer mPlayer = null;
public MyMediaPlayerService() {
}
public int onStartCommand(Intent intent, int flags, int startId) {
if (mPlayer != null && mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
mPlayer = new MediaPlayer();
}
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(intent.getStringExtra("streamurl"));
mPlayer.setLooping(true);
} catch (IOException e) {
e.printStackTrace();
}
mPlayer.setOnPreparedListener(this);
// Request audio focus for playback
mPlayer.prepareAsync();
mPlayer.setLooping(false);
mPlayer.setOnCompletionListener(this);
notification();
return START_NOT_STICKY;
}
Live radio streaming, it's long running process irrespective of UI, so you need to implement complete media player logic in service and your service will be take all the charge for streaming. As per as ui is concerned whatever UI component you are using to represent the streamed data can communicate with service you will implement.
And regarding start and stop streaming, it will be depend on your application design.
I think this approach will be open for all expected application design.
Let me know if you need any help.

Android MediaPlayer OnCompletionListener not called in JUnit Testcase (AndroidTestCase)!

I am using the Android MediaPlayer class and trying to write a testcase which verifies that the onCompletion method is called.
I use it to play the next track after the previous one is finished.
When I run the app using the emulator (2.1 or 4.0) the onCompletion method is called and the next track starts playing, but in the testcase it is not.
Here is the simplified code:
public class MediaPlayerControllerTest extends AndroidTestCase implements OnCompletionListener {
public void testContinuePlayNextTrack() {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
try {
mediaPlayer.setDataSource("/mnt/sdcard/5749/01.mp3");
mediaPlayer.prepare();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaPlayer.start();
}
#Override
public void onCompletion(MediaPlayer mp) {
System.out.println("ON COMPLETION!!!!!");
}
}
The code above is normally part of a class MediPlayerController which is used in the app and the test, so it's the same class. I broke the problem down to the few lines of code above.
This cost me a lot of hours. I hope someone has a solution!
Thanks a lot!!!
I have encountered this problem, and nothing was working for me. From the official Site (click me) for the MediaPlayer one can find the following sentence:
In order to receive the respective callback associated with these listeners, applications are required to create MediaPlayer objects on a thread with its own Looper running (main UI thread by default has a Looper running).
I was a bit lost, as there was no hint for this need on in the API for onCompletionListener himself.
I think the problem is that your test case is no longer running when the MediaPlayer finishes playing the mp3. So your solution is to keep the test case alive until the onCompletion() is fired.
I had a similar issue when playing a file from an IntentService. The Service was being destroyed before the callback was initiated.
Actually, the reason is that the MediaPlayer is a local variable. After the testContinuePlayNextTrack() is finished, the MediaPlayer is collected by GC. So the fix is easy, make your MediaPlayer a member of the class.
public class MediaPlayerControllerTest extends AndroidTestCase implements OnCompletionListener {
MediaPlayer mediaPlayer = new MediaPlayer();
public void testContinuePlayNextTrack() {
mediaPlayer.setOnCompletionListener(this);
try {
mediaPlayer.setDataSource("/mnt/sdcard/5749/01.mp3");
mediaPlayer.prepare();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaPlayer.start();
}
#Override
public void onCompletion(MediaPlayer mp) {
System.out.println("ON COMPLETION!!!!!");
}
}

Starting media player in a thread problem

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.

Categories

Resources