Fixed alarm not ringing because of RingtoneActivity being resumed on next launch and not created
This commit is contained in:
parent
1ea774f21b
commit
53d5eed670
@ -24,8 +24,6 @@
|
||||
android:label="@string/title_activity_ringtone"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:excludeFromRecents="true"
|
||||
android:finishOnTaskLaunch="true"
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity="com.philliphsu.clock2.RingtoneActivity">
|
||||
</activity>
|
||||
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
package com.philliphsu.clock2.ringtone;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
@ -20,7 +24,8 @@ import static com.philliphsu.clock2.util.Preconditions.checkNotNull;
|
||||
* TODO: Make this abstract and make appropriate subclasses for Alarms and Timers.
|
||||
* TODO: Implement dismiss and extend logic here.
|
||||
*/
|
||||
public class RingtoneActivity extends AppCompatActivity {
|
||||
public class RingtoneActivity extends AppCompatActivity implements RingtoneService.RingtoneCallback {
|
||||
private static final String TAG = "RingtoneActivity";
|
||||
|
||||
// Shared with RingtoneService
|
||||
public static final String EXTRA_ITEM_ID = "com.philliphsu.clock2.ringtone.extra.ITEM_ID";
|
||||
@ -37,12 +42,15 @@ public class RingtoneActivity extends AppCompatActivity {
|
||||
}
|
||||
mAlarm = checkNotNull(AlarmsRepository.getInstance(this).getItem(id));
|
||||
|
||||
// TODO: If the upcoming alarm notification isn't present, verify other notifications aren't affected.
|
||||
// This could be the case if we're starting a new instance of this activity after leaving the first launch.
|
||||
AlarmUtils.removeUpcomingAlarmNotification(this, mAlarm);
|
||||
|
||||
// Play the ringtone
|
||||
Intent intent = new Intent(this, RingtoneService.class)
|
||||
.putExtra(EXTRA_ITEM_ID, mAlarm.id());
|
||||
startService(intent);
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
|
||||
Button snooze = (Button) findViewById(R.id.btn_snooze);
|
||||
snooze.setOnClickListener(new View.OnClickListener() {
|
||||
@ -84,6 +92,24 @@ public class RingtoneActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Capture the back press and return. We want to limit the user's options for leaving
|
||||
// this activity as much as possible.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
unbindService(mConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutoSilence() {
|
||||
// Service should have stopped itself by this point
|
||||
finish();
|
||||
}
|
||||
|
||||
private void snooze() {
|
||||
mAlarm.snooze(1); // TODO: Read snooze duration from prefs
|
||||
AlarmUtils.scheduleAlarm(this, mAlarm);
|
||||
@ -97,4 +123,19 @@ public class RingtoneActivity extends AppCompatActivity {
|
||||
// TODO: Do we need to cancel the PendingIntent and the alarm in AlarmManager?
|
||||
finish();
|
||||
}
|
||||
|
||||
private RingtoneService mBoundService; // TODO: Don't need? Only used locally in ServiceConnection.
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mBoundService = ((RingtoneService.RingtoneBinder) service).getService();
|
||||
mBoundService.setRingtoneCallback(RingtoneActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mBoundService = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -9,6 +9,7 @@ import android.media.AudioManager;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
@ -28,6 +29,17 @@ import static com.philliphsu.clock2.util.Preconditions.checkNotNull;
|
||||
* of the RingtoneService will be tied to that of its RingtoneActivity because users are not likely to
|
||||
* navigate away from the Activity without making an action. But if they do accidentally navigate away,
|
||||
* they have plenty of time to make the desired action via the notification.
|
||||
*
|
||||
* This is both a started and bound service. See https://developer.android.com/guide/components/bound-services.html#Lifecycle
|
||||
* "... the service runs until the service stops itself with stopSelf() or another component
|
||||
* calls stopService(), regardless of whether it is bound to any clients."
|
||||
* The regardless phrase didn't work for me. I had to unbind in RingtoneActivity first before calling
|
||||
* stopSelf() on this service for the ringtone to stop playing.
|
||||
* TODO: Consider making this purely a bound service, so you don't have to bind/unbind AND start/stop
|
||||
* manually. Instead of implementing onStartCommand() and calling startService(), you would write a public
|
||||
* method that the activity calls to start playing the ringtone. When the activity calls its onDestroy(), it unbinds
|
||||
* itself from this service, and the system will know to destroy this service instead of you manually
|
||||
* calling stopSelf() or stopService().
|
||||
*/
|
||||
public class RingtoneService extends Service { // TODO: abstract this, make subclasses
|
||||
private static final String TAG = "RingtoneService";
|
||||
@ -37,6 +49,7 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
|
||||
private Alarm mAlarm;
|
||||
private String mNormalRingTime;
|
||||
private boolean mAutoSilenced = false;
|
||||
private RingtoneCallback mRingtoneCallback;
|
||||
// TODO: Using Handler for this is ill-suited? Alarm ringing could outlast the
|
||||
// application's life. Use AlarmManager API instead.
|
||||
private final Handler mSilenceHandler = new Handler();
|
||||
@ -44,9 +57,17 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
|
||||
@Override
|
||||
public void run() {
|
||||
mAutoSilenced = true;
|
||||
if (mRingtoneCallback != null) {
|
||||
// Finish the activity, which fires onDestroy() and then unbinds itself from this service.
|
||||
// All clients must be unbound before stopSelf() (and stopService()?) will succeed.
|
||||
// See https://developer.android.com/guide/components/bound-services.html#Lifecycle
|
||||
// Figure 1 regarding the lifecycle of started and bound services.
|
||||
mRingtoneCallback.onAutoSilence();
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
};
|
||||
private final IBinder mBinder = new RingtoneBinder();
|
||||
|
||||
// TODO: Apply the setting for "Silence after" here by using an AlarmManager to
|
||||
// schedule an alarm in the future to stop this service, and also update the foreground
|
||||
@ -121,7 +142,22 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null; // Binding to this service is not supported
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
public void setRingtoneCallback(RingtoneCallback callback) {
|
||||
mRingtoneCallback = callback;
|
||||
}
|
||||
|
||||
// Needed so clients can get the Service instance and e.g. call setRingtoneCallback().
|
||||
public class RingtoneBinder extends Binder {
|
||||
RingtoneService getService() {
|
||||
return RingtoneService.this;
|
||||
}
|
||||
}
|
||||
|
||||
public interface RingtoneCallback {
|
||||
void onAutoSilence();
|
||||
}
|
||||
|
||||
private void scheduleAutoSilence() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user