My code plays a song from a listview, everything perfect, BUT, if I specifically rotate it, the media player stop, how can i keep it playing?
and! if i create an another button to pause, or something like that, should I use the same answer?
my code in a button:
testme.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if(nombre.matches("Kaminomi")) { //ignore this
try {
mp.setDataSource(nombreSong);
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
if (validar == false) {
validar = true;
mp.start();
Toast.makeText(getApplicationContext(), "Reproduciendo ahora: \n" + nombreSong, Toast.LENGTH_LONG).show();
testme.setText("Stop :D");
testme.setCompoundDrawablesWithIntrinsicBounds(R.drawable.nisekoi1,0,0,0);
} else {
validar = false;
Toast.makeText(getApplicationContext(), "Deteniendo: \n" + nombreSong, Toast.LENGTH_LONG).show();
mp.stop();
testme.setText("Play :D");
}
}else{
Toast.makeText(getApplicationContext(), "Algo mas creo", Toast.LENGTH_LONG).show(); //ignore this too
}
}
Put this in your manifest xml file:
<activity android:name="MainActivity"
android:configChanges="keyboardHidden|orientation">
i.e. add android:configChanges="keyboardHidden|orientation" to the activity xml element.
Whats happening is that when your screen orientation changes, a configuration change occurs and this causes Android to destroy and recreate your activity.
The above code in my answer will prevent a configuration change from happening when an orientation change or a keyboard change occurs.
However this is just a workaround. A configuration change can occur at any time (e.g. placing the phone in a docking station) and therefore just disabling configuration changes for orientation changes and keyboard changes is not enough.
To properly maintain the state of objects during configuration changes, Fragments are a good approach.
Related
I have a bit of a weird one that I can't quite figure out.
When I log out of my app via the navigation menu, it takes me back to the login screen. I have then set it up so that when the user presses the back button twice, it should close the app completely. I have got the toast to appear after one press to say the user needs to press twice but here's my issue.
When I press back twice, the screen clears but the login screen pops back up again. With my last login details in the boxes. Then if I press back twice again, it closes the app completely. I need to try and figure out why it won't close the app on the first two presses of the back button.
Below is the code I am using:
public void onBackPressed() {
//moveTaskToBack(true);
if (!isUserClickedBackButton){
Toast.makeText(this, "Press back again to exit", Toast.LENGTH_SHORT).show();
isUserClickedBackButton = true;
} else {
System.exit(0); // exits right out of app
super.onBackPressed();
}
}
I have tried not using 'super.onBackPressed', I've tried using it on its own. I've tried adding 'finish()' or just using that on its own. I'm at a loss. Has anyone got any ideas?
I'm using Firebase for authentication if that makes any difference.
Thanks in advance.
You can use:
super.onBackPressed();
And add in the AndroidManifest.xml to the login activity tag:
android:noHistory="true"
You Can do it without using no History in android manifest if you want...
//Use this as class variable..
boolean doublePressedBackExit = false;
#Override
public void onBackPressed() {
if (doublePressedBackExit) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
System.exit(0);
return;
}
this.doublePressedBackExit = true;
Toast.makeText(getApplicationContext(), "Press again to exit..", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doublePressedBackExit = false;
}
}, 2000);
}
I am building an app with flash cards. When you click the "next" button it plays a sound(the name of the card) and it also plays the same sound if you click on the card. The only thing is when I click on the "next" button it plays the sound twice, simultaneously, causing it to sound robotic. I assume I'm calling the sound twice by accident but I don't know where or how to fix it. I've been looking all over the place but can't find a way to fix this.
Here is my code:
private String[] soundfile={"aa.m4a","bb.m4a...
public void onClick(View arg0) {...
//when btnplay is clicked
else if(arg0.getId()==R.id.imagenumber){
//call the method playsound
playSound(soundfile[screennumber].toString());
}//end btnsound clicked
//begin changeCard
private void changeCard(int screen){
switch (screen){
case 0: imagenumber.setImageResource(aa);
mediap2 = MediaPlayer.create(this, R.raw.aa);
break;...
mediap2.start();
}//end changeCard
//begin playSound on click
public void playSound(String soundName){
Boolean mpPlayingStatus;
try{//try to check MediaPlayer status
mpPlayingStatus=mp.isPlaying();
}
catch (Exception e){
mpPlayingStatus=false;
}
if(mpPlayingStatus==true){//if the MediaPlayer is playing a voice, stop it to play new voice
mp.stop();
mp.release();//remove sound from memory
}
else{
try
{
mp = new MediaPlayer();
AssetFileDescriptor afd = getAssets().openFd(soundName);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
mp.start();//play sound
}//try block
catch(Exception e) {
Log.i("Error playing sound: ", e.toString());
}
}
}//end playSound
Thanks for the help!
Oh wow. I figured it out. This whole time I thought it was strictly an issue with the sound itself but it turns out the problem was here:
if(arg0.getId()==R.id.btnprevious){
screennumber--;//minus 1 to the screennumber
changeNumber(screennumber);
if(screennumber==0){
//disable btnprevious
btnprevious.setEnabled(false);
}else{
//enable btnprevious
btnprevious.setEnabled(true);
}
changeNumber(screennumber);
btnnext.setEnabled(true);
}
Where I called changeNumber(screennumber);
btnnext.setEnabled(true);
twice. Silly mistake. Thanks for your help anyway!
Hey guys so I'm trying to display gps distance between the user and some place on a card they can see. The problem is, I think the main thread splits or does 2 things at once. At the code below, Android makes a toast while doing the code in the if(flag) statement... so it toasts the GPS difference without getting the coordinates of the user...How do i make it so that, it does if(flag) statement first then goes on to do the toast after and outside the if statement?
#Override
public void onResume()
{
super.onResume();
ImagePath = getIntent().getStringExtra("imagePath");
if(ImagePath == null)
{
Toast.makeText(this,"hello everyone",Toast.LENGTH_LONG).show();
}
if(newCardAdded)
{
flag = displayGpsStatus();
if(flag)
{
editLocation.setText("Please!! move your device to" +
" see the changes in coordinates." + "\nWait..");
pb.setVisibility(View.VISIBLE);
locationListener = new MyLocationListener();//LocationListener actually physically gets your location
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
}
else
{
alertbox("Gps Status!!", "Your GPS is: OFF");
}
Global_Class.getInstance().getValue().getlatitude = place_lat;
Global_Class.getInstance().getValue().getlongitutde = place_lon;
String gps_distance = String.valueOf(gps_difference(user_lon, user_lat,place_lon,place_lat));
Toast.makeText(this, gps_distance, Toast.LENGTH_LONG).show();
}
}
LocationManager#requestLocationUpdates
Your locationListener must implement onLocationChanged(Location) method, which will be called for each location update. Then calculate distance and make a toast in that method. Because requestLocationUpdates(...) runs in another thread, there's no way to confirm that it is done before Toast.makeText(...), so you must use your MyLocationListener.
I have a seekbar in my fragment that I use to show the progress of a MediaPlayertrack that is playing. Everything works as expected until I change orientation of the device. I save my fragment instance and load it back, and all of the other views are repopulated as they should be, and the music keeps right on playing as it should, but the seekbar goes right to the max, as if the track has reached it's max duration. The runnable that is updating the seekbar based on the mediaplayer's position keeps running after the orientation change as well, and logging the currentPos value in the runnable shows that it stays in sync with the mMediaPlayer.getCurrentPosition() as it should, even after the orientation change...So basically, it continues to feed the correct position to the seekbar; the seekbar just isn't updating after the orientation change. It makes me wonder if the seekbar instance stays the same after the change. If it doesn't stay the same instance, I can't figure out why or how to fix it.
The onCLick method of my play button calls the following to start the track and hook up the seekbar to it:
private void startPlayer(String url){
try {
mMediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
playerState = PlayerState.PLAYING;
setButtonsForPlayerState();
setSeekBarValues();
mHandler = new Handler();
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (mMediaPlayer != null ) {
int currentPos = mMediaPlayer.getCurrentPosition();
Log.e(LOG_TAG, "Current pos is " + currentPos);
seekBar.setProgress(currentPos);
if (currentPos<10000){
seekBarStartTime.setText("0:0" + currentPos / 1000);
}else{
seekBarStartTime.setText("0:" + currentPos / 1000);
}
}
if (mMediaPlayer.isPlaying()){
mHandler.postDelayed(this, 50);
}
}
}
);
}
});
}
and here is the setSeekBarValues() method that is called in the above method:
private void setSeekBarValues() {
seekBar.setMax(mMediaPlayer.getDuration());
seekBarFinishTime.setText("0:" + seekBar.getMax()/1000);
seekBar.setProgress(0);
}
seekBarStartTime and seekBarFinishTime are just TextViews that show the current position and end time of the track, respectivily.
Since all of my other views, streaming music, etc. seems to be working as it should on the re-creation of Activity and Fragment, I don't think it's an issue with saving instance state, but if you want me to post that code as well please let me know.
Any ideas are appreciated.
I know you can seekto() with Mediaplayer, to start at a certain point.
But is there a way to make a track (the audio playing) stop at a certain point? Or would an if statement on a timer loop have to be used?
Doesn't seem possible (correct me if I'm wrong) to do this with media player without resorting to seekto() in a timer loop. However you could try using an AudioTrack in conjunction with setting a notification marker:
AudioTrack.setNotificationMarkerPosition
Sets the position of the notification marker.
and overriding the playback position update listener AudioTrack.OnPlaybackPositionUpdateListener
Interface definition for a callback to be invoked when the playback head position of an AudioTrack has reached a notification marker or has increased by a certain period.
You have to make threat that will trigger getCurrentPosition().
When it will reach stop point, you have to stop MediaPlayer.
public void run() {
while (mp != null && mPosition < mTotal) {
try {
Thread.sleep(500); // you can modify sleep time for better accuracy
if (mp.isPlaying()) {
mPosition = mp.getCurrentPosition();
if (mPosition == mYourStopPoint) { //remember to set mYourStopPoint
mp.stop();
break;
}
}
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
}
}
Start this Thread in onPreapared callback.
public void onPrepared(MediaPlayer genericPlayer) {
mTotal = mp.getDuration();
new Thread(this).start();
}
Sadly, AudioTrack's position callbacks appear to be fairly seriously broken. http://code.google.com/p/android/issues/detail?id=2563