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.
Related
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;
}
}
I'm developing a simple music player, but an error appeared sometimes(just one line error):
Error: start called in state 0, mPlayer(0x0)
I have a MusicService for operating something about music. Part of it:
#Override
public void onCreate() {
super.onCreate();
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnCompletionListener(this);
}
...
public void play(String url) {
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
...
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
addTimer();
status = MUSIC_STATUS_PLAYING;
}
When I open a Activity, and bind MusicService, execute play(), the error appeared sometimes.
Any idea?
I had the same issue in Kotlin, and I was able to tackle it.
In my case I added the MediaPlayer.create() inside a Boolean statement, so let's say in fragment 1 I use a Boolean called "globalAudio", I set this Boolean globally true from "MyModel" class, hence it will execute MediaPlayer.create as normal since it is true outside the conditional body. But, if I move to fragment 2 and set the Boolean "globalAudio" to false and when I go back to fragment 1, the Logcat will throw me error "pause called in state 64, mPlayer(0xca47c070)" and "error (-38, 0)", because I am attempting to start the audio without Media.create() being set up.
I attached the problem and the solution below to make the understanding easier for you
Problem
if (MyModel.StaticData.globalAudio) { // A
homeAudio = MediaPlayer.create(requireActivity(), R.raw.background1)
homeAudio.setVolume(MyModel.StaticData.backgroundVolume, MyModel.StaticData.backgroundVolume)
}
if (homeAudio.isPlaying) { // B
homeAudio.pause() // pause
homeAudio.seekTo(0) // set start from 00:00
}
if (!homeAudio.isPlaying) { // C
homeAudio.start() // throws error if A is not executed
}
Solution
//A
homeAudio = MediaPlayer.create(requireActivity(), R.raw.background1)
homeAudio.setVolume(MyModel.StaticData.backgroundVolume, MyModel.StaticData.backgroundVolume)
if (homeAudio.isPlaying) { // B
homeAudio.pause() // pause
homeAudio.seekTo(0) // set start from 00:00
}
if (!homeAudio.isPlaying) { // C
homeAudio.start() // won't throw error because A is always executed
}
Here I provide you a Kotlin code that it can be automatically converted to Java in Android Studio:
var myAudio = MediaPlayer.create(requireActivity(), R.raw.[yourAudio])
myAudio.setVolume([leftChannelInFLoat], [rightChannelInFLoat])
if (myAudio.isPlaying) {
myAudio.pause()
myAudio.seekTo(0)
}
if (!hmyAudio.isPlaying) {
myAudio.start()
}
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.
I'm using an Android MediaPlayer instance which is simple initialized by:
mediaPlayer = MediaPlayer.create(this,R.raw.conrnfield);
I also got this Thread updating a SeekBar according to the track playing progress.
updateTime = new Runnable() {
#Override
public void run() {
int currentPosition = 0;
int total = mediaPlayer.getDuration();
seekBar.setMax(total);
while (mediaPlayer != null && currentPosition < total) {
try {
Thread.sleep(500);
currentPosition = mediaPlayer.getCurrentPosition();
}
catch (InterruptedException ex) {return;}
catch (Exception e) {return;}
seekBar.setProgress(currentPosition);
}
}
};
I got a method to change the current track:
public void changeSong(View view) {
mediaPlayer.reset();
mediaPlayer.start();
mediaPlayer.selectTrack(2);
}
However, when I invoke this method, it causes the app to crash. I can see first at the log a
java.lang.IllegalStateException: Could not execute method of the activity
error message at the stacktrace.
I can't even know if my approach is wrong. This is whole log
You should use MediaPlayer.setDataSource after a call to MediaPlayer.reset. Note that the MediaPlayer.create methods are just helper methods that call MediaPlayer.setDataSource, and are suppose to be used to play one off media. In the example following context is your Activity so you could probably replace them with MainActivity.this.
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(context.getPackageName())
.appendPath(String.valueOf(R.raw.conrnfield))
.build();
mediaPlayer.setDataSource(context, uri);
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.