Android: Saving screen state (Beginner) - android

I have come across an issue with my application, I have an "option" class which has a ToggleButton in it which handles the playback of music (on or off) which I created in a Session. However, if I turn the music off, change screen and go back to the option class, the ToggleButton goes back to "on", even though the music is no longer playing, which means I have to press the button twice for the music to actually come back on. Does anyone have any ideas?
Service Class:
public class MyMusicService extends Service {
MediaPlayer mp;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mp = MediaPlayer.create(this, R.raw.song);
mp.start();
mp.setLooping(true);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(mp!=null) {
mp.stop();
mp.release();
}
mp=null;
}
}
Option class:
public class OptionsActivity extends Activity {
Intent i; // Handles MyMusicService.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.options);
//setting the layout
i=new Intent(this, MyMusicService.class);
final ToggleButton soundOption = (ToggleButton) findViewById(R.id.soundPref);
soundOption.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on clicks to control sound being on and off.
if (soundOption.isChecked()) {
Toast.makeText(OptionsActivity.this, "Music on.", Toast.LENGTH_SHORT).show();
startService(i);
} else {
stopService(i);
Toast.makeText(OptionsActivity.this, "Music off.", Toast.LENGTH_SHORT).show();
}
}});
}
}
MainActvitiy class
Intent i;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//setting the layout
//Auto starts playing music on app launch.
i = new Intent(this,MyMusicService.class);
startService(i);
Could it be something to do with the fact in the XML I have:
android:checked="true"
Thanks for any help.

Yes, the ToggleButton will be initialized anew, when you come back to this view, so android:checked="true" comes back into play.
You can use the method myToggleButton.setChecked(boolean isMusicPlaying) to reset the state of the Button.
So you have to check whether the music is playing or not, when you come back to this view and set the state of the button accordingly.
You can use the method as described in another thread to find out if your music service is running.
private boolean isMyServiceRunning(String serviceCanonicalClassName) {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceCanonicalClassName.equals(service.service.getClassName())) {
return true;
}
}
return false;
}
so you simply call it to find out of your service is running.
And then, right after finding out where your ToggleButton is in your layout, you can define if it should be toggled or not:
boolean musicPlays = isMyServiceRunning(MyMusicService.class.getCanonicalName());
final ToggleButton soundOption = (ToggleButton) findViewById(R.id.soundPref);
soundOption.setChecked(musicPlays)

Related

play music with background service

I'm trying to play music with a background service. Firstly, I have a toggle button in MainActivity for playing and pausing music. I also created
BackgroundSoundService just for playing music in all activities and not to play in the background:
public class BackgroundSoundService extends Service {
private static final String TAG = "BackgroundSoundService";
MediaPlayer player;
public IBinder onBind(Intent arg0) {
Log.i(TAG, "onBind()" );
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.vaporv2);
player.setLooping(true); // Set looping
player.setVolume(100,100);
Log.i(TAG, "onCreate() , service started...");
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return Service.START_STICKY;
}
public IBinder onUnBind(Intent arg0) {
Log.i(TAG, "onUnBind()");
return null;
}
public void onStop() {
Log.i(TAG, "onStop()");
}
public void onPause() {
if(player!=null && player.isPlaying()){
player.pause();
}
Log.i(TAG, "onPause()");
}
#Override
public void onDestroy() {
player.stop();
player.release();
Log.i(TAG, "onCreate() , service stopped...");
}
#Override
public void onLowMemory() {
Log.i(TAG, "onLowMemory()");
}
}
and MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MusicButton = (ToggleButton) findViewById(R.id.toggleButton);
MusicButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (MusicButton.isChecked()) {
//mediaPlayer.pause();
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
startService(myService);
} else {
//mediaPlayer.start();
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
stopService(myService);
}
}
});
My problem happens when I pause the music and play it again. The music starts from the beginning when I want it to continue from where it left off. My second problem is that I don't want to play music in the background, I want stop music when the app is in background.
I'm not sure what your onPause() and onStop() are meant to do. However when you start a service for the first time using Context.startService() the onCreate() method of the service is called and then onStartCommand() is called and later when you call startService() again only the onStartCommand() is called. So for whatever reason if you want to play the sound in a service and pause that in the very same service, you need to provide the service an Action that specifies the action you want to do.
So in your activity when you want to tell the service to play the sound:
String action = "PLAY";
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
myService.setAction(action);
startService(myService);
and to pause the sound:
String action = "PAUSE";
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
myService.setAction(action);
startService(myService);
and in the onStartCommand() method in your service:
if (intent.getAction().equals("PLAY")) {
// resume the sound
}
if (intent.getAction().equals("PAUSE")) {
// pause the sound
}
and when you really need to stop the service meaning Destroy the service, call context.stopService() and only then onDestroy() method is called and the service is really destroyed.
To prevent playing in background override on Activity pause then pause you service there and to resume where you left of save the current position in a preference then retrieve it when needed

Making WebView audio play in background

I am making an android app for my website. It has some videos which are somewhat like podcasts. I want the app to be able to play the audio in the background when the user either locks the screen or is using other applications. To achieve this, I have a WebView in place. To provide the above mentioned functionality, I tried to use a PARTIAL_WAKE_LOCK in the activity. This only continues to play the audio when the screen is locked, but not when the home button is pressed (ie. in the background). Is there a workaround for this issue?
If You want your app to keep running the Audio even if it is in Background, You have to run the Mediaplayer in a Separate Service.
This service will keep on Running even the app goes to background or comes back.
You can even write a sticky service to keep running(with foreground as true) if the app gets killed.
You should use android service to play the music independent of your activity.Please look at this example:
Here is my Android Service class:
class MusicService extends Service implements OnCompletionListener {
MediaPlayer mediaPlayer;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
mediaPlayer = MediaPlayer.create(this, R.raw.s);// raw/s.mp3
mediaPlayer.setOnCompletionListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
return START_STICKY;
}
public void onDestroy() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
}
public void onCompletion(MediaPlayer _mediaPlayer) {
stopSelf();
}
}
Here is Activity:
public class MusicActivity extends Activity implements OnClickListener {
Button startPlaybackButton, stopPlaybackButton;
Intent playbackServiceIntent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startPlaybackButton = (Button) this.findViewById(R.id.StartPlaybackButton);
stopPlaybackButton = (Button) this.findViewById(R.id.StopPlaybackButton);
startPlaybackButton.setOnClickListener(this);
stopPlaybackButton.setOnClickListener(this);
playbackServiceIntent = new Intent(this,MusicService.class);
}
public void onClick(View v) {
if (v == startPlaybackButton) {
startService(playbackServiceIntent);
finish();
} else if (v == stopPlaybackButton) {
stopService(playbackServiceIntent);
finish();
}
}
}
Please do not forget to add the service in your manifest file :
<service android:enabled="true" android:name=".services.MusicService" />

How to pause the service when the home button is pressed and resume the service when the program is resume?

public class BackgroundMusicService extends Service
{
int currentPos;
/** indicates how to behave if the service is killed */
int mStartMode;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
MediaPlayer player;
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.tornado);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
player.seekTo(currentPos);
player.start();
return 1;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return mAllowRebind;
}
#Override
public void onRebind(Intent intent) {
}
public void onPause()
{
player.pause();
}
#Override
public void onDestroy() {
player.stop();
currentPos = player.getCurrentPosition();
}
}
This is the service that play the background music, how to pause the service when the home button is pressed and resume the service when the program is resume? and here is my MainActivity:
public class MainActivity extends ActionBarActivity
{
int request_code = 1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(getBaseContext(), BackgroundMusicService.class));
}
#Override
protected void onDestroy()
{
super.onDestroy();
stopService(new Intent(getBaseContext(), BackgroundMusicService.class));
}
}
I think need to use onPause() and onResume() function, but how to use it? and it should be use in service class or the activity class?
One more thing need to consider, I used multiple intent, and make sure that when I change to 2nd or others intents, the service is still running, means that changing intent will not stop playing the background music...unless home button is pressed or quit the program(this one I already done).
You have your onPause and onResume methods. You generally don't need to extend the Application class but instead use it in your Activity (esp if your app only has one Activity).
However, why start and stop the service? Why not just pause/unpause the music? You can send an intent to pause/unpause (or even toggle) the music playback.

How to stop service on home key press [duplicate]

This question already has answers here:
Press home button to stop service
(3 answers)
Closed 6 years ago.
I am implementing following service to play sound. This sound stop when someone press on any menu button. But If I press home key of device sound still playing. I am adding this code
#Override
protected void onPause() {
super.onPause();
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
}
in my activity class. But still sound not stop. why onPause method is not working?
Service code-
public class PlayAudio extends Service{
private static final String LOGCAT = null;
MediaPlayer objPlayer;
public void onCreate(){
super.onCreate();
Log.d(LOGCAT, "Service Started!");
objPlayer = MediaPlayer.create(this, R.raw.test);
}
public int onStartCommand(Intent intent, int flags, int startId){
objPlayer.start();
Log.d(LOGCAT, "Media Player started!");
if(objPlayer.isLooping() != true){
Log.d(LOGCAT, "Problem in Playing Audio");
}
return 1;
}
public void onStop(){
objPlayer.stop();
objPlayer.release();
}
public void onPause(){
objPlayer.stop();
objPlayer.release();
}
public void onDestroy(){
objPlayer.stop();
objPlayer.release();
}
#Override
public IBinder onBind(Intent objIndent) {
return null;
}
}
you can stop service on home key press..try this
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_HOME)
{
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
}
});
write one Thread in Service which continuosly checks for running tasks and stop the Service if top task's top activity package name is equal to the package name of launcher app...
new Thread() {
public void run() {
final List<ResolveInfo> activities = getPackageManager().queryIntentActivities(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), 0);
final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
while(true) {
String packageName = activityManager.getRunningTasks(5).get(0).topActivity.getPackageName();
if(activities.contains(packageName)) {
break;
}
try {
Thread.sleep(500); // wait for half second
} catch (InterruptedException e) {
}
}
stopSelf();
};
}.start();

Trying to make a pause/resume music activity using service

I'm trying to create an activity with one button in its layout which will pause or resume the music when it's pressed. the problem is that when it's pressed to resume the music it starts the audio file all over again. Any idea how to make it play from the last point it stopped rather than restarting it?
Main activity
public class MainActivity extends Activity implements OnClickListener {
private Boolean isMusicPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View musicButton = findViewById(R.id.music_button);
musicButton.setOnClickListener(this);
startService(new Intent(getBaseContext(), MusicService.class));
isMusicPlaying = true;
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.music_button)
if (isMusicPlaying) stopService(new Intent(getBaseContext(),
MusicService.class));
else startService(new Intent(getBaseContext(), MusicService.class));
isMusicPlaying = !isMusicPlaying;
}
}
Service class
public class MusicService extends Service {
MediaPlayer player;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.song);
player.setLooping(true); // Set looping
player.setVolume(100, 100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return START_STICKY;
}
#Override
public void onDestroy() {
player.pause();
}
}
It seems like MediaPlayer object in your service is not kept when you stop the service.
You can get the current position of your song using getCurrentPosition() method before you stop your service,
player.pause();
currentPos = player.getCurrentPosition();
and send this value back to activity before it is stopped.
Then, you can use seekTo(int) method to move to specified time position before playing.
player.seekTo(currentPos);
player.start();
For communication between your service and activity, you might register broadcastreceiver and communicate using intent or use a bound service.
UPDATE:
I found following tutorial and you'd better to follow this. It's about using a service with MediaPlayer.
Especially, you are not using prepare method at all when you initialize your MediaPlayer. put these lines:
player.setOnPreparedListener(this);
player.prepareAsync();
and add listener:
public void onPrepared(MediaPlayer player) {
player.start();
}
http://developer.android.com/guide/topics/media/mediaplayer.html#mpandservices
Seeing that the activity is re-started why don't you save the states to Shared Preferences

Categories

Resources