Reputation: 261
I'm writing an application that show an activity at fixed time.
I start the activity from service with such code:
intent.setClass(context, FakeAction.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
in the onCreate method of FakeAction I require wake up of device and start sound message:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
There is a lot of code in onCreate to show information on screen and start the sound message.
Here is an onPause method:
@Override
protected void onPause()
{
Log.i(TAG, "onPause");
//Stop mediaPlayer
if(mp != null)
{
if(mp.isPlaying())mp.stop();
mp.release();
mp = null;
}
//Restore volume
if(audioManager != null)
{
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, savedVolume, 0);
}
//Stop minute timer
handler.removeCallbacks(minuteReceiver);
super.onPause();
}
Unfortunately the onPause() method is called immediately after onCreate. So my sound message is immediately stopped.
But if the activity is started when the screen is not locked then the onPasue() is not called immediately after onCreate();
Even though I comment all of "getWindow().addFlags()" strings the onPause() is called after onCreate() when the screen if locked.
The question is why onPause is called immediately after onCreate? How can I distinguish immediate call of onPause() method and call of onPause() when user press the back button?
Below is the code of the activity. I use the MVP pattern, so, the main code is in presenter. But even if I comment all presenter's calls (like I done in this example) the onPause() is called immediately after onCreate()
Can it have a sence that I start activity in AsyncTask? The AsyncTask is started form service. The service is stopped after the AsyncTask if finished.
public class FakeAction extends RoboActivity
implements
View.OnClickListener
,AlarmAction
{
private static final String TAG = "TA FakeAction";
@InjectView(R.id.aa_btn_Stop) Button btnStop;
@InjectView(R.id.aa_btn_Snooze) Button btnSnooze;
@InjectView(R.id.aa_tv_CurTime) TextView tvCurTime;
@InjectView(R.id.aa_tv_CurDate) TextView tvCurDate;
@InjectView(R.id.aa_tv_AlarmName) TextView tvAlarmName;
@Inject public AlarmActionPresenter presenter;
private Exception ex;
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
setContentView(R.layout.alarm_action);
try
{
//presenter.onCreate(this);
}
catch(Exception ex)
{
this.ex = ex;
Log.e(TAG, "onCreate", ex);
}
btnStop.setOnClickListener(this);
btnSnooze.setOnClickListener(this);
}
@Override
protected void onPause()
{
Log.i(TAG, "onPause");
//presenter.onPause();
super.onPause();
}
@Override
public void onClick(View v)
{
Log.i(TAG, "onClick");
//presenter.onClick(v.getId());
}
@Override
public Bundle getIntentBundle()
{
return getIntent().getExtras();
}
@Override
public void setAlarmName(String alarmName)
{
tvAlarmName.setText(alarmName);
}
@Override
public String getAlarmName()
{
return tvAlarmName.getText().toString();
}
@Override
public void setCurTime(String curTime)
{
tvCurTime.setText(curTime);
}
@Override
public String getCurTime()
{
return tvCurTime.getText().toString();
}
@Override
public void setCurDate(String curDate)
{
tvCurDate.setText(curDate);
}
@Override
public String getCurDate()
{
return tvCurDate.getText().toString();
}
@Override
public IAssetFileDescriptorMockable openFd(String assetName) throws IOException
{
Log.i(TAG, "openFd");
return new AssetFileDescriptorMockable(getAssets().openFd(assetName));
}
}
Upvotes: 21
Views: 13943
Reputation: 1275
I solved my problem by testing wheter the screen is on or off with this code:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (!powerManager.isScreenOn()){
return;
}
Use code if stop sound activity when press home button. onPause
not acive until screen is not on.
@Override
protected void onPause() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (powerManager.isScreenOn()){
Log.e("Test two", "****");
Intent i = new Intent(this, RingtonePlayingService.class);
stopService(i);
finish();
}
super.onPause();
}
So the code in the onPause
method is only done if the screen is On. When the screen is turning on and onPause
is called the isScreenOn
method of PowerManager
returns false.
Upvotes: 3
Reputation: 6646
If you have ES File Explorer
then FORCE STOP it. Somehow, they interrupt your app's lifecycle (comments suggest some kind of overlay).
My issue with onResume
being caused twice was because onPause
was somehow being called after the activity was created.. something was interrupting my app.
And this only happens after being opened for the first time after installation or built from studio.
I got the clue from another post and found out it was because of ES File Explorer. Why does onResume() seem to be called twice?
As soon as I force stop ES File Explorer, this hiccup behavior no longer happens... it's frustrating to know after trying many other proposed solutions. So beware of any other interrupting apps like this one.
Upvotes: 0
Reputation: 261
I found out the solution of my problem.
The reason why the onPause called after onCreate is the ActivityManager. In the log I've found the line immediately after onCreate: "Activity pause timeout for HistoryRecord" So, next events happened in my Activity:
I don't know how to prevent the "Activity pause timeout for HistoryRecord" but I changed my application so it starts the sound message in onResume(). Even though it is stopped in onPause() it is started again in next onResume().
Upvotes: 5
Reputation: 3231
Here is what I think happens, then : your service creates your activity, and your activity does several things, such as waking up the screen and dismissing the keyguard. But it's not instant, which means that the keyguard activity is probably woken up before being dismissed, thus pausing your activity for a short while.
I think what you should is this : http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
Deal with it using intent. You catch the intent saying that the screen is on, and the intent that the screen is off.
The cycle will work like that, I think :
That means : when the onPause is called, the screen is off ! Meaning : you just need a flag, and if this flag says that the screen is still off, you don't pause the music.
It's a bit dirty, but should work perfectly.
Upvotes: 4
Reputation: 536
You can distinguish onPause() call between Acticity itself and back button press.
onBackPressed(){
// set isBackPressed = true;
}
onPause(){
if(isBackPressed ){
// exit due to back pressed.
}else{
// normal exit.
}
}
Upvotes: 0
Reputation:
Start an intent that will check if the user is exiting and tie that to your exit button. I am still unsure what you want as the code is incomplete
Upvotes: 1