简体   繁体   中英

Alarm keeps playing after onPause called

Here's code for a timer that plays a sound once it reaches 0 (timer works fine). The problem is the sound persists even through onPause() in MainActivity.java called.

I implemented onDestroy() in SimpleIntentService.java to stop the sound, but apparently it's never called even with finish() in the calling Activity . How am I supposed to make the sound stop when the app is paused?

Here's my MainActivity.java

public class MainActivity extends Activity {

    private BroadcastReceiver broadcastReceiver;
    NumberPicker picker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        picker = (NumberPicker) findViewById(minutePicker);

        Log.i("TurnToTech", "Project Name - SimpleBackgroundService");

        picker.setMinValue(0);
        picker.setMaxValue(20);

        broadcastReceiver = new BroadcastReceiver(){
            @Override
            public void onReceive(Context arg0, Intent intent) {
                   String text = intent.getStringExtra(SimpleIntentService.PARAM_OUT_MSG);
                   Toast.makeText(getApplicationContext(),
                            text, Toast.LENGTH_SHORT).show();
            }
        };
    }

    Intent msgIntent;

    public void startTimer(View view) {
        setContentView(R.layout.activity_main);

        msgIntent = new Intent(this, SimpleIntentService.class);
        msgIntent.putExtra(SimpleIntentService.PARAM_IN_MSG, "Alarm: ");
        msgIntent.putExtra("time", picker.getValue());

        startService(msgIntent);
    }

    public void onResume() {
        super.onResume();

        IntentFilter filter = new IntentFilter(SimpleIntentService.ACTION_RESP);
        filter.addCategory(Intent.CATEGORY_DEFAULT);

        registerReceiver(broadcastReceiver,filter);
      }

      public void onPause() {
          finish();
          unregisterReceiver(broadcastReceiver);
          super.onPause();
      }
}

And the SimpleIntentService.java

public class SimpleIntentService extends IntentService {
    public static final String PARAM_IN_MSG = "in_msg";
    public static final String PARAM_OUT_MSG = "out_msg";
    int time;

    public static final String ACTION_RESP = "org.turntotech.intent.action.MESSAGE_PROCESSED";

    public SimpleIntentService() {
        super("SimpleIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        System.out.println("SimpleIntentService Called");
        String msg = intent.getStringExtra(PARAM_IN_MSG);
        int time = intent.getIntExtra("time", 0);

        // Timer implementation
        if (time == 0 ){
            playSound();
        }

        while(time > 0){

            SystemClock.sleep(5000); // 5 seconds
            time -= 5;
            String resultTxt = msg + time + " seconds remaining";
            Intent broadcastIntent = new Intent();

            broadcastIntent.setAction(ACTION_RESP);
            broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
            broadcastIntent.putExtra(PARAM_OUT_MSG, resultTxt);
            broadcastIntent.putExtra("time", time);

            sendBroadcast(broadcastIntent);
            if (time == 0) {
                playSound();
            }
        }
    }

    Uri alert;

    public void playSound(){
        alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
        Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
        r.play();
    }

    public void onDestroy() {
        Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
        r.stop();

        super.onDestroy();
    }
}

In your IntentService you're not really stopping the same alarm in your onDestroy function. Because each time you're getting a new instance of it.

So I would like to suggest to keep a public static variable of Ringtone so that it can be accessed from everywhere. Declare them in your MainActivity .

public static Ringtone r; 
public static Uri alert;

Initialize them in the onCreate function of your MainActivity .

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ... Other statements 

    // Initialize ringtone here
    initializeRingtone();
}

private void initializeRingtone() {
    alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
    r = RingtoneManager.getRingtone(getApplicationContext(), alert);
}

Now the onPause() function of your MainActivity should look like this

public void onPause() {
    unregisterReceiver(broadcastReceiver);
    r.stop();
    super.onPause();
}

And if you want to play the sound after you resume the application from background and then the timer runs out, you might consider doing something like this in the onResume function of your MainActivity

public void onResume() {
    super.onResume();
    registerReceiver(broadcastReceiver);
    initializeRingtone();  // Initialize it again. 
}

And the playSound() function in the IntentService might look like this.

public void playSound(){
    // Initialize the alert and ringtone again. 
    MainActivity.alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
    MainActivity.r = RingtoneManager.getRingtone(getApplicationContext(), alert);

    MainActivity.r.play();
}

public void onDestroy() {
    MainActivity.r.stop();
    super.onDestroy();
}

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM