I am currently working on Chat application. In this there is feature of sending voice notes. The sending and playing of voice notes is working fine. But the problem is that when I play the voice notes, the previous voice notes playing not stoping.. both are playing together.
here is my code for playing voice notes,
public static class MessageViewHolder extends RecyclerView.ViewHolder {
private TextView messageTextView;
private ImageView messageImageView;
private TextView timeTextView;
private LinearLayout textMessageLayout;
private TextView messengerNameTextView;
private CircleImageView messengerPhotoImageView;
ImageView leftQuackImage, rightQuackImage;
private LinearLayout voiceNotesLayout;
private ImageView playImageView, stopImageView;
private SeekBar progressSeekbar;
private MediaPlayer mPlayer;
double timeElapsed = 0, finalTime = 0;
Handler durationHandler = new Handler();
Runnable updateSeekBarTime;
boolean isPlaying;
public MessageViewHolder(View itemView) {
super(itemView);
messageTextView = (TextView) itemView.findViewById(R.id.messageTextView);
messageImageView = (ImageView) itemView.findViewById(R.id.messageImageView);
timeTextView = (TextView) itemView.findViewById(R.id.timeTextView);
textMessageLayout = (LinearLayout) itemView.findViewById(R.id.textMessageLayout);
messengerNameTextView = (TextView) itemView.findViewById(R.id.messengerTextView);
messengerPhotoImageView = (CircleImageView) itemView.findViewById(R.id.messengerImageView);
leftQuackImage = (ImageView) itemView.findViewById(R.id.leftQuackImage);
rightQuackImage = (ImageView) itemView.findViewById(R.id.rightQuackImage);
voiceNotesLayout = (LinearLayout) itemView.findViewById(R.id.voiceNotesLayout);
playImageView = (ImageView) itemView.findViewById(R.id.playImageView);
stopImageView = (ImageView) itemView.findViewById(R.id.stopImageView);
progressSeekbar = (SeekBar) itemView.findViewById(R.id.progressSeekbar);
isPlaying = false;
mPlayer = new MediaPlayer();
}
public void setupAudioPlay(final long duration, final String url){
progressSeekbar.setMax((int) duration);
progressSeekbar.setClickable(false);
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mPlayer.setDataSource(url);
mPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}catch (IllegalStateException e){
e.printStackTrace();
}
playImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Media player","isPlaying"+mPlayer.isPlaying()+isPlaying);
if (mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
if (!isPlaying) {
isPlaying = true;
mPlayer.start();
playImageView.setVisibility(View.GONE);
stopImageView.setVisibility(View.VISIBLE);
timeElapsed = mPlayer.getCurrentPosition();
progressSeekbar.setProgress((int) timeElapsed);
durationHandler.postDelayed(updateSeekBarTime, 100);
} else {
isPlaying = false;
mPlayer.pause();
}
}
});
stopImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (isPlaying) {
if (stopPlaying()) {
playImageView.setVisibility(View.VISIBLE);
stopImageView.setVisibility(View.GONE);
}
}
}
});
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (mp != null) {
mPlayer.seekTo(0);
isPlaying = false;
progressSeekbar.setProgress(0);
}
playImageView.setVisibility(View.VISIBLE);
stopImageView.setVisibility(View.GONE);
}
});
updateSeekBarTime = new Runnable() {
public void run() {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
timeElapsed = mPlayer.getCurrentPosition();
progressSeekbar.setProgress((int) timeElapsed);
durationHandler.postDelayed(this, 100);
} else {
mPlayer.pause();
isPlaying = false;
progressSeekbar.setProgress(0);
playImageView.setVisibility(View.VISIBLE);
stopImageView.setVisibility(View.GONE);
}
}
}
};
}
private boolean stopPlaying() {
mPlayer.pause();
mPlayer.seekTo(0);
if (!mPlayer.isPlaying()) {
return true;
}
return false;
}
}
here the mPlayer.isPlaying always gets false.
Please Help me!
From the documentation:
When the call to pause() returns, the MediaPlayer object enters the Paused state. Note that the transition from the Started state to the Paused state and vice versa happens asynchronously in the player engine. It may take some time before the state is updated in calls to isPlaying(), and it can be a number of seconds in the case of streamed content.
This may be the case here. The reasons why sound is not stopping and why isPlaying() returns true might be different. For example multiple instances of MediaPlayer might exist in parallel, making mPlayer static would exclude such an option.
You can check the system Audio status whenever it is necessary. In your case, whenever the play button is clicked the condition below should be checked first.
AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
if(manager.isMusicActive())
{
// to do
}
In to do part you should implement the primary action which is:
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PAUSE);
audioManager.dispatchMediaKeyEvent(event);
You can find the whole documentation here
Related
I want to show a custom XML dialog dialogue that will appear after a specific time in the first run, let's say after a min
how can I do it
but I'm confused about what should I do in a situation like below
if the user open the app for the first time and just spent 30 sec and just pause the app(screen lock or in onPause) or just close the app completely
Just as a note - I have already implemented a one time show dialog(directly in main activity without any layout file ) when the app runs for the first time already
Code
To view the already implemented dialog(shows up on the first run) please
go to the // Caution dialog (showDialog method)
MainActivity.java
public class MainActivity extends AppCompatActivity {
MediaPlayer player1;
MediaPlayer player2;
SeekBar seekBar1;
SeekBar seekBar2;
TextView elapsedTimeLable1;
TextView elapsedTimeLable2;
TextView remainingTimeLable1;
TextView remainingTimeLable2;
ImageView play1;
ImageView play2;
int totalTime1;
#SuppressLint("HandlerLeak")
private final Handler handler1 = new Handler() {
#SuppressLint("SetTextI18n")
#Override
public void handleMessage(#NonNull Message msg) {
int currentPosition1 = msg.what;
//Update SeekBar
seekBar1.setProgress(currentPosition1);
// Update Timelable
String elapsedTime1 = createTimerLable1(currentPosition1);
elapsedTimeLable1.setText(elapsedTime1);
String remainingTime1 = createTimerLable1(totalTime1 - currentPosition1);
remainingTimeLable1.setText("- " + remainingTime1);
}
};
int totalTime2;
#SuppressLint("HandlerLeak")
private final Handler handler2 = new Handler() {
#SuppressLint("SetTextI18n")
#Override
public void handleMessage(#NonNull Message msg) {
int currentPosition2 = msg.what;
// Update SeekBar
seekBar2.setProgress(currentPosition2);
// Update Timelable
String elapsedTime2 = createTimerLable2(currentPosition2);
elapsedTimeLable2.setText(elapsedTime2);
String remainingTime2 = createTimerLable2(totalTime2 - currentPosition2);
remainingTimeLable2.setText("- " + remainingTime2);
}
};
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#SuppressLint("ObsoleteSdkInt")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window w = getWindow();
// clear FLAG_TRANSLUCENT_STATUS flag:
w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// finally change the color
w.setStatusBarColor(ContextCompat.getColor(this, R.color.Card_Elevation_Color));
}
// PlayButton * The ButtonClick is in the last if you want to jump directly there *
play1 = findViewById(R.id.playbtn1);
play2 = findViewById(R.id.playbtn2);
// TimeLables
elapsedTimeLable1 = findViewById(R.id.cTime1);
elapsedTimeLable2 = findViewById(R.id.cTime2);
remainingTimeLable1 = findViewById(R.id.tTime1);
remainingTimeLable2 = findViewById(R.id.tTime2);
// MediaPlayer
player1 = MediaPlayer.create(this, R.raw.dog_howl);
player1.setLooping(true);
player1.seekTo(0);
totalTime1 = player1.getDuration();
player2 = MediaPlayer.create(this, R.raw.dog_bark);
player2.setLooping(true);
player2.seekTo(0);
totalTime2 = player2.getDuration();
//SeekBar
seekBar1 = findViewById(R.id.seekbar1);
seekBar2 = findViewById(R.id.seekbar2);
seekBar1.setMax(totalTime1);
seekBar2.setMax(totalTime2);
seekBar1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress1, boolean fromUser1) {
if (fromUser1) {
player1.seekTo(progress1);
seekBar1.setProgress(progress1);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBar2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress2, boolean fromUser2) {
if (fromUser2) {
player2.seekTo(progress2);
seekBar2.setProgress(progress2);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Thread (Update SeekBar & TimeLabel)
new Thread(() -> {
while (player1 != null) {
try {
Message msg = new Message();
msg.what = player1.getCurrentPosition();
handler1.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
}
}).start();
new Thread(() -> {
while (player2 != null) {
try {
Message msg = new Message();
msg.what = player2.getCurrentPosition();
handler2.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
}
}).start();
// Admob Banner Ad
MobileAds.initialize(this, initializationStatus -> {
});
AdView mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
// Caution dialog
SharedPreferences preferences = getSharedPreferences("prefs", MODE_PRIVATE);
boolean firstStart = preferences.getBoolean("firstStart", true);
if (firstStart) {
showDialog();
}
}
// Caution dialog
private void showDialog() {
new AlertDialog.Builder(this)
.setTitle("Caution!")
.setMessage("In case you're wearing any kind of headphones please remove it before playing the ' Howl ' audio")
.setPositiveButton("ok", (dialogInterface, i) -> dialogInterface.dismiss())
.create().show();
SharedPreferences preferences = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("firstStart", false);
editor.apply();
}
public String createTimerLable1(int duration) {
String timerLabel1 = "";
int min = duration / 1000 / 60;
int sec = duration / 1000 % 60;
timerLabel1 += min + ":";
if (sec < 10) timerLabel1 += "0";
timerLabel1 += sec;
return timerLabel1;
}
public String createTimerLable2(int duration) {
String timerLabel2 = "";
int min = duration / 1000 / 60;
int sec = duration / 1000 % 60;
timerLabel2 += min + ":";
if (sec < 10) timerLabel2 += "0";
timerLabel2 += sec;
return timerLabel2;
}
public void playBtnClick1(View view) {
if (player2.isPlaying()) {
player2.pause();
play2.setImageResource(R.drawable.ic_baseline_play_circle_filled_24);
}
if (!player1.isPlaying()) {
// Stoping
player1.start();
play1.setImageResource(R.drawable.ic_baseline_pause_circle_filled_24);
} else {
// Playing
player1.pause();
play1.setImageResource(R.drawable.ic_baseline_play_circle_filled_24);
}
}
public void playBtnClick2(View view) {
if (player1.isPlaying()) {
player1.pause();
play1.setImageResource(R.drawable.ic_baseline_play_circle_filled_24);
}
if (!player2.isPlaying()) {
// Stoping
player2.start();
play2.setImageResource(R.drawable.ic_baseline_pause_circle_filled_24);
} else {
// Playing
player2.pause();
play2.setImageResource(R.drawable.ic_baseline_play_circle_filled_24);
}
}
#Override
protected void onPause() {
super.onPause();
if (player1 != null) {
player1.pause();
play1.setImageResource(R.drawable.ic_baseline_play_circle_filled_24);
}
if (player2 != null) {
player2.pause();
play2.setImageResource(R.drawable.ic_baseline_play_circle_filled_24);
}
}
}
but I'm confused about what should I do in a situation like below
if the user open the app for the first time and just spent 30 sec and just pause the app(screen lock or in onPause) or just close the
app completely
This is impossible to do if your app is closed.My suggestion would be to create a service on another process that does this dialog such that even if the app process is closed,the service process will still be running unless it is stopped explicitly.
Defining a Process of a Service
The android:process field defines the name of the process where the
service is to run. Normally, all components of an application run in
the default process created for the application. However, a component
can override the default with its own process attribute, allowing you
to spread your application across multiple processes.
If the name assigned to this attribute begins with a colon (':'), the
service will run in its own separate process.
<service android:name="com.example.appName" android:process=":externalProcess" />
This is of course in the manifest file .
You might also need to show a system dialog thus you will need a system Alert Window permission i your manifest and request for the permision on runtime.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Then on runtime request like this:
public static void openOverlaySettings(Activity activity) {
final Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.getPackageName()));
try {
activity.startActivityForResult(intent, 6);
} catch (ActivityNotFoundException e) {
Log.e("Drawers permission :", e.getMessage());
}
}
To check if granted use :
if(!Settings.canDrawOverlays(context)) {
openOverlaySettings(context);
ok=false;
}
Then in your service you should create the dialog like below
View aldv= LayoutInflater.from(act).inflate(R.layout.your_layout,null);
ald=new AlertDialog.Builder(act,R.style.AppTheme)
.setView(aldv)
.setCancelable(true)
.create();
ald.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
I'm developing a Whack-a-mole game in Android Studio and I'm having a hard time with AsyncTask (our teacher told us to use it).
Basically the AsyncTasks are not doing anything.
I tried using one asynctask to increase an int and change a textview with the new value each time it increased and it worked, however it doesn't work for what I want it to do.
TextView tv;
ImageView iv1;
ImageView iv2;
ImageView iv3;
ImageView iv4;
boolean salir = false;
int puntuacion = 0;
int vidas = 3;
Hilo hilo;
Hilo hilo2;
Hilo hilo3;
Hilo hilo4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
tv = findViewById(R.id.textView);
iv1 = findViewById(R.id.imageView);
iv2 = findViewById(R.id.imageView2);
iv3 = findViewById(R.id.imageView3);
iv4 = findViewById(R.id.imageView4);
hilo = new Hilo(iv1);
hilo2 = new Hilo(iv2);
hilo3 = new Hilo(iv3);
hilo4 = new Hilo(iv4);
hilo.execute();
hilo2.execute();
hilo3.execute();
hilo4.execute();
}
public void updatePuntuacion() {
tv.setText("Puntuacion: " + puntuacion);
}
public void updateVidas() {
}
private class Hilo extends AsyncTask<Void, Void, Integer> {
boolean estado = false;
ImageView img;
public Hilo (ImageView img) {
this.img = img;
}
#Override
protected Integer doInBackground(Void... voids) {
while(!salir){
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (estado) {
puntuacion++;
updatePuntuacion();
} else {
vidas--;
updateVidas();
}
}
});
if(estado) {
try {
Thread.sleep(Math.round(Math.random()*5000+2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
img.setImageResource(R.drawable.topo);
estado=true;
publishProgress();
} else {
try {
Thread.sleep(Math.round(Math.random()*3000+1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
img.setImageResource(R.drawable.blank);
estado=false;
publishProgress();
}
if(puntuacion == 100) {
salir=true;
}
if(vidas == 0) {
salir = true;
}
}
return puntuacion;
}
}
I expect the imageviews to change it's image every X secs (those are random) but they don't.
I hope you guys can help me, thanks in advance!!!
You need to understand how an Async task works.
You cannot do all the work in "doInBackground" .
You need to remove the onClickListener form "doInBackground" .
Start your async task in the imageview onClick and
After your complete your background processing stuff in "doInBackground" ,
set the image to imageview in "onPostExecute" .
Please go through this https://developer.android.com/reference/android/os/AsyncTask
to understand what an Async Task is first
I am using hourglass library for a countdown. Lets say 5 minutes. During that time i am playing the same 5 audio files over and over. This is working great. The problem is with the pause. When its on the first audio. It pauses and resumes just fine. After it gets to the next song, and i pause it, it throws a IllegalStateException.
The code is a bit ugly. In onCompletion it keeps playing the files until it gets to the end. Then i call playAudio() and the cycle starts over until the hour glass has reached zero.
pause.setOnClickListener(new View.OnClickListener() is a floating action button and i toggle between pause icon and play icon
Java Class code
tracks[0] = R.raw.audio0;
tracks[1] = R.raw.audio1;
tracks[2] = R.raw.audio2;
tracks[3] = R.raw.audio3;
tracks[4] = R.raw.audio4;
countDown = (TextView) findViewById(R.id.txtCountdown);
cancel = (FloatingActionButton)findViewById(R.id.cancelMeditation);
pause = (FloatingActionButton)findViewById(R.id.pauseMeditation);
Intent intent = getIntent();
check = intent.getIntExtra("DURATION", -1);
milliseconds = check * 60000;
countDown.setText("" + String.format("%d min",
TimeUnit.MILLISECONDS.toMinutes(milliseconds)));
pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(hourglass == null){
startTimer(milliseconds);
currentTrack = 0;
isTimerDone = false;
playAudio();
pause.setImageResource(R.drawable.ic_pause);
return;
}
if(hourglass.isPaused()){
hourglass.resumeTimer();
pause.setImageResource(R.drawable.ic_pause);
isPaused = false;
mediaAffyPlayer.seekTo(length);
mediaAffyPlayer.start();
}else if(hourglass.isRunning()){
hourglass.pauseTimer();
pause.setImageResource(R.drawable.ic_play1);
isPaused = true;
if(mediaAffyPlayer != null) {
mediaAffyPlayer.pause();
length = mediaAffyPlayer.getCurrentPosition();
}
} else{
startTimer(milliseconds);
playAudio();
}
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
public void startTimer(long milliseconds){
hourglass = new Hourglass(milliseconds, 1000) {
#Override
public void onTimerTick(long timeRemaining) {
countDown.setText("" + String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes(timeRemaining),
TimeUnit.MILLISECONDS.toSeconds(timeRemaining) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeRemaining))));
if(TimeUnit.MILLISECONDS.toMinutes(timeRemaining) ==0){
return;
}
}
#Override
public void onTimerFinish() {
isTimerDone = true;
}
};
hourglass.startTimer();
}
private void playAudio(){
if(mediaAffyPlayer == null){
mediaAffyPlayer = MediaPlayer.create(getApplicationContext(), tracks[0]);
mediaAffyPlayer.setOnCompletionListener(this);
mediaAffyPlayer.start();
isPaused = false;
return;
}
if(mediaAffyPlayer != null) {
mediaAffyPlayer.release();
mediaAffyPlayer = MediaPlayer.create(getApplicationContext(), tracks[0]);
mediaAffyPlayer.setOnCompletionListener(this);
isPaused = false;
mediaAffyPlayer.start();
}
mediaAffyPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
});
}
public void onCompletion(MediaPlayer mediaPlayer) {
if (currentTrack < tracks.length - 1) {
if(isTimerDone){
countDown.setText("" + String.format("%d min",
TimeUnit.MILLISECONDS.toMinutes(milliseconds)));
pause.setImageResource(R.drawable.ic_play1);
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer=null;
hourglass = null;
return;
}
currentTrack++;
mediaPlayer.release();
mediaPlayer = MediaPlayer.create(getApplicationContext(), tracks[currentTrack]);
mediaPlayer.setOnCompletionListener(ShowMeditationActivity.this);
mediaPlayer.start();
} else {
if(!isTimerDone){
currentTrack = 0;
playAudio();
}
}
}
Exception
java.lang.IllegalStateException
at android.media.MediaPlayer._pause(Native Method)
at android.media.MediaPlayer.pause(MediaPlayer.java:1512)
Which throws it at mediaAffyPlayer.pause(); in hourglass.isRunning()
I know the code is ugly, but I just think that when it plays the second track the media player object has changed and thats why it throws error. I just dont know how to fix it.
Any help is appreciated as i already burned through many hours trying to fix it.
Thanks
EDIT I fixed the issue.
I commented out the code in OnCompletion that created and played the mediaplayer. I called playAudio() and stuck the code in there.
private void playAudio(){
if(mediaAffyPlayer == null){
mediaAffyPlayer = MediaPlayer.create(getApplicationContext(), tracks[0]);
mediaAffyPlayer.setOnCompletionListener(this);
mediaAffyPlayer.start();
isPaused = false;
return;
}
if(mediaAffyPlayer != null) {
currentTrack++;
mediaAffyPlayer.release();
mediaAffyPlayer = MediaPlayer.create(getApplicationContext(), tracks[currentTrack]);
mediaAffyPlayer.setOnCompletionListener(ShowMeditationActivity.this);
mediaAffyPlayer.start();
}
Problem with isPaused() code
try with this!!
try{
if (mediaAffyPlayer.isPlaying()) {
mediaAffyPlayer.pause();
}
}catch(Exception we){
we.printStackTrace();
}
I do apologize for the noobish question, but I am building a music player in android studio and I am having problems with the songs playing one after the other like a playlist. The songs can only be picked by hand and after the song finishes it just stops until the user clicks another song. I've written two pieces of code that I suspect will solve this issue but I'm not really sure how to implement them or if they eventually will be of any use at all. I would really appreciate some help with this, could really really use it. Any advice or constructive criticism is always welcome, thanks in advance. here are the snippets:
//------------> to get the next song <---------------
int itemsInList=list.getAdapter().getCount();
for(int i=1;i<itemsInList;i++){
list.setSelection(i);
}
//--------------> to play the song on list item click <-------------------
#Override
protected void onListItemClick(ListView list, View view, int position,
long id) {
super.onListItemClick(list, view, position, id);
currentFile = (String) view.getTag();
startPlay(currentFile);
}
And just for reference here is my main java file:
public class MainActivity extends ListActivity {
private static final int UPDATE_FREQUENCY = 500;
private static final int STEP_VALUE = 4000;
private MediaCursorAdapter mediaAdapter = null;
private TextView selectedFile = null;
private SeekBar seekbar = null;
private MediaPlayer player = null;
private ListView list = null;
private ImageButton playButton = null;
private ImageButton prevButton = null;
private ImageButton nextButton = null;
private ImageButton btNext = null;
private ImageButton btPrev = null;
private boolean isStarted = true;
private String currentFile = "";
private boolean isMovingSeekBar = false;
private final Handler handler = new Handler();
private final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
selectedFile = (TextView) findViewById(R.id.selectedfile);
seekbar = (SeekBar) findViewById(R.id.seekbar);
playButton = (ImageButton) findViewById(R.id.play);
prevButton = (ImageButton) findViewById(R.id.prev);
nextButton = (ImageButton) findViewById(R.id.next);
btNext = (ImageButton) findViewById(R.id.btNxt);
btPrev = (ImageButton) findViewById(R.id.btPrev);
player = new MediaPlayer();
player.setOnCompletionListener(onCompletion);
player.setOnErrorListener(onError);
seekbar.setOnSeekBarChangeListener(seekBarChanged);
Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
if (null != cursor) {
cursor.moveToFirst();
mediaAdapter = new MediaCursorAdapter(this, R.layout.list_item, cursor);
setListAdapter(mediaAdapter);
playButton.setOnClickListener(onButtonClick);
nextButton.setOnClickListener(onButtonClick);
prevButton.setOnClickListener(onButtonClick);
btNext.setOnClickListener(onButtonClick);
btPrev.setOnClickListener(onButtonClick);
}
}
//----------- ??? ----------------------------------------------------------------
int itemsInList=list.getAdapter().getCount();
for(int i=1;i<itemsInList;i++){
list.setSelection(i);
}
#Override
protected void onListItemClick(ListView list, View view, int position, long id) {
super.onListItemClick(list, view, position, id);
currentFile = (String) view.getTag();
startPlay(currentFile);
}
// --------------------------------------------------------------------------------
#Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(updatePositionRunnable);
player.stop();
player.reset();
player.release();
player = null;
}
private void startPlay(String file) {
Log.i("Selected: ", file);
selectedFile.setText(file);
seekbar.setProgress(0);
player.stop();
player.reset();
try {
player.setDataSource(file);
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
seekbar.setMax(player.getDuration());
playButton.setImageResource(android.R.drawable.ic_media_pause);
updatePosition();
isStarted = true;
}
private void stopPlay() {
player.stop();
player.reset();
playButton.setImageResource(android.R.drawable.ic_media_play);
handler.removeCallbacks(updatePositionRunnable);
seekbar.setProgress(0);
isStarted = false;
}
private void updatePosition() {
handler.removeCallbacks(updatePositionRunnable);
seekbar.setProgress(player.getCurrentPosition());
handler.postDelayed(updatePositionRunnable, UPDATE_FREQUENCY);
}
private class MediaCursorAdapter extends SimpleCursorAdapter {
public MediaCursorAdapter(Context context, int layout, Cursor c) {
super(context, layout, c,
new String[]{MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.TITLE, MediaStore.Audio.AudioColumns.DURATION},
new int[]{R.id.displayname, R.id.title, R.id.duration});
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView title = (TextView) view.findViewById(R.id.title);
TextView name = (TextView) view.findViewById(R.id.displayname);
TextView duration = (TextView) view.findViewById(R.id.duration);
name.setText(cursor.getString(
cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)));
title.setText(cursor.getString(
cursor.getColumnIndex(MediaStore.MediaColumns.TITLE)));
long durationInMs = Long.parseLong(cursor.getString(
cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION)));
double durationInMin = ((double) durationInMs / 1000.0) / 60.0;
durationInMin = new BigDecimal(Double.toString(durationInMin)).setScale(2, BigDecimal.ROUND_UP).doubleValue();
duration.setText("" + durationInMin);
view.setTag(cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA)));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.list_item, parent, false);
bindView(v, context, cursor);
return v;
}
}
private View.OnClickListener onButtonClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play: {
if (player.isPlaying()) {
handler.removeCallbacks(updatePositionRunnable);
player.pause();
playButton.setImageResource(android.R.drawable.ic_media_play);
} else {
if (isStarted) {
player.start();
playButton.setImageResource(android.R.drawable.ic_media_pause);
updatePosition();
} else {
startPlay(currentFile);
}
}
break;
}
case R.id.next: {
int seekto = player.getCurrentPosition() + STEP_VALUE;
if (seekto > player.getDuration())
seekto = player.getDuration();
player.pause();
player.seekTo(seekto);
player.start();
break;
}
case R.id.prev: {
int seekto = player.getCurrentPosition() - STEP_VALUE;
if (seekto < 0)
seekto = 0;
player.pause();
player.seekTo(seekto);
player.start();
break;
}
case R.id.btNxt: {
//TO DO
}
case R.id.btPrev: {
//TO DO
}
}
}
};
private MediaPlayer.OnCompletionListener onCompletion = new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stopPlay();
}
};
private MediaPlayer.OnErrorListener onError = new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
};
private SeekBar.OnSeekBarChangeListener seekBarChanged = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
isMovingSeekBar = false;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
isMovingSeekBar = true;
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (isMovingSeekBar) {
player.seekTo(progress);
Log.i("OnSeekBarChangeListener", "onProgressChanged");
}
}
};
}
You can look at my methods below to play the next song. Hope it helps.
public static void nextSong() {
int numOfSong = songList.size();
if (!isShuffle) { // Shuffle mode is off
if (currentPosition < numOfSong - 1) {
currentPosition++;
currentSong = songList.get(currentPosition);
Log.d("my_log", "position = "+currentPosition);
playBackMusic();
} else {
currentPosition = 0;
currentSong = songList.get(currentPosition);
Log.d("my_log", "position = "+currentPosition);
playBackMusic();
}
} else { // Shuffle mode is on
Random rand = new Random();
currentPosition = rand.nextInt(numOfSong);
currentSong = songList.get(currentPosition);
Log.d("my_log", "position = "+currentPosition);
playBackMusic();
}
}
And this is playBackMusic() method to play the song:
public static void playBackMusic() {
try {
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(currentSong.getPath());
mediaPlayer.prepare();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
endOfTheSong();
}
});
isPlaying = true;
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
Method endOfTheSong() to handle what to do after playing current song.
public static void endOfTheSong() {
if (isRepeat == 1) { // currently repeat one song
mediaPlayer.seekTo(0);
mediaPlayer.start();
} else if (isRepeat == 2) { // currently repeat all songs
nextSong();
} else { // currently no repeat
if (currentPosition != songList.size() - 1) nextSong();
}
}
The use case is this, in Android (above Kit Kat): open a stream from an audio file, get its properties, modify the memory buffer and play the result.
I would like to know how to 1) properly create the stream from the audio file; 2) get its properties (channels, encoding, length) like for the javax.sound.sampled.AudioFormat, but using methods from the android.media framework.
I know how to build a stream from binary, add audio properties to it then playing it. I would like to do the other way and extract these properties (channels, encoding) from the existing sound file header, using latest classes of the Android framework.
Thanks!
Here is full streaming class use this :
public class MainActivity extends Activity implements OnClickListener,
OnTouchListener, OnCompletionListener, OnBufferingUpdateListener {
private Button btn_play, btn_pause, btn_stop;
private SeekBar seekBar;
private MediaPlayer mediaPlayer;
private int lengthOfAudio;
private final String URL = "http://songspkcompilations.com/indian/soulfularijit/%5BSongs.PK%5D%2012%20-%20Mickey%20Virus%20-%20Tose%20Naina.mp3";
private static final int MINUTES_IN_AN_HOUR = 60;
private static final int SECONDS_IN_A_MINUTE = 60;
private final Handler handler = new Handler();
private boolean is_loading = true;
private boolean is_stopped = false;
private final Runnable r = new Runnable() {
#Override
public void run() {
updateSeekProgress();
}
};
private TextView txtTime;
private ProgressBar musicProgress;
private ImageView artistImg;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize_Controls();
}
private void initialize_Controls() {
btn_play = (Button) findViewById(R.id.btn_play);
btn_play.setOnClickListener(this);
btn_pause = (Button) findViewById(R.id.btn_pause);
btn_pause.setOnClickListener(this);
btn_pause.setEnabled(false);
btn_stop = (Button) findViewById(R.id.btn_stop);
btn_stop.setOnClickListener(this);
btn_stop.setEnabled(false);
musicProgress = (ProgressBar) findViewById(R.id.progress);
artistImg = (ImageView) findViewById(R.id.artistImg);
seekBar = (SeekBar) findViewById(R.id.seekBar);
seekBar.setOnTouchListener(this);
txtTime = (TextView) findViewById(R.id.time);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int percent) {
seekBar.setSecondaryProgress(percent);
}
#Override
public void onCompletion(MediaPlayer mp) {
btn_play.setEnabled(true);
btn_pause.setEnabled(false);
btn_stop.setEnabled(false);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (mediaPlayer.isPlaying()) {
SeekBar tmpSeekBar = (SeekBar) v;
mediaPlayer
.seekTo((lengthOfAudio / 100) * tmpSeekBar.getProgress());
}
return false;
}
#Override
public void onClick(View view) {
try {
mediaPlayer.setDataSource(URL);
mediaPlayer.prepare();
lengthOfAudio = mediaPlayer.getDuration();
} catch (Exception e) {
// Log.e("Error", e.getMessage());
}
switch (view.getId()) {
case R.id.btn_play:
if (is_stopped) {
is_stopped = false;
mediaPlayer.seekTo(0);
}
playAudio();
break;
case R.id.btn_pause:
pauseAudio();
break;
case R.id.btn_stop:
stopAudio();
break;
default:
break;
}
updateSeekProgress();
}
private void updateSeekProgress() {
if (mediaPlayer.isPlaying()) {
if (is_loading) {
is_loading = false;
musicProgress.setVisibility(View.GONE);
artistImg.setVisibility(View.VISIBLE);
}
int progress = (int) (((float) mediaPlayer.getCurrentPosition() / lengthOfAudio) * 100);
int remainSec = (lengthOfAudio - mediaPlayer.getCurrentPosition()) / 1000;
seekBar.setProgress(progress);
txtTime.setText("" + timeConversion(remainSec));
handler.postDelayed(r, 1000);
}
}
private void stopAudio() {
if (mediaPlayer != null) {
mediaPlayer.pause();
is_stopped = true;
}
seekBar.setProgress(0);
seekBar.setSecondaryProgress(0);
txtTime.setText("" + timeConversion(lengthOfAudio / 1000));
btn_play.setEnabled(true);
btn_pause.setEnabled(false);
btn_stop.setEnabled(false);
}
private void pauseAudio() {
if (mediaPlayer != null) {
mediaPlayer.pause();
}
btn_play.setEnabled(true);
btn_pause.setEnabled(false);
}
private void playAudio() {
if (mediaPlayer != null) {
mediaPlayer.start();
}
btn_play.setEnabled(false);
btn_pause.setEnabled(true);
btn_stop.setEnabled(true);
}
private static String timeConversion(int totalSeconds) {
int hours = totalSeconds / MINUTES_IN_AN_HOUR / SECONDS_IN_A_MINUTE;
int minutes = (totalSeconds - (hoursToSeconds(hours)))
/ SECONDS_IN_A_MINUTE;
int seconds = totalSeconds
- ((hoursToSeconds(hours)) + (minutesToSeconds(minutes)));
return hours + ":" + minutes + ":" + seconds;
}
private static int hoursToSeconds(int hours) {
return hours * MINUTES_IN_AN_HOUR * SECONDS_IN_A_MINUTE;
}
private static int minutesToSeconds(int minutes) {
return minutes * SECONDS_IN_A_MINUTE;
}
class PlayTask extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try {
mediaPlayer.setDataSource(URL);
mediaPlayer.prepare();
lengthOfAudio = mediaPlayer.getDuration();
} catch (Exception e) {
// Log.e("Error", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
playAudio();
updateSeekProgress();
}
}
#Override
protected void onResume() {
super.onResume();
new PlayTask().execute();
}
#Override
public void onBackPressed() {
super.onBackPressed();
pauseAudio();
finish();
}
}