How do I stop playing sound by switching between t

2019-09-06 01:24发布

问题:

I have made an alarm clock and there I have used a toggle switch to start my alarm. What I want is as soon as the user click on the button again, it should stop the alarm (ring). Toggling between ON and OFF wil start and stop respectively.

But right now, I am only able to start my alarm. In fact it never gets stopped. If I switch the button OFF the sound gets played even faster, that is very strange. How can I stop it? I have pasted the only part of code where I am assuming the problem occurs. If you need to look at my whole app's code I will post it. [NOTE: everything else works fine]

MainActivity:

    package com.mycompany.alarmclock;
//I haven't post the imported stuff here, they are in my file
import android.support.v7.app.ActionBarActivity;
import java.util.Calendar;
public class MainActivity extends Activity {

    AlarmManager alarmManager;
    private PendingIntent pendingIntent;//an action to be performed by other/foreign application
    private TimePicker alarmTimePicker;//In where the user set the time
    private static MainActivity inst;
    private TextView alarmTextView;//the area where alarm message/notification will be displayed


    public static MainActivity instance() {
        return inst;
    }

    public void onStart() {
        super.onStart();
        inst = this;
    }

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

        alarmTimePicker = (TimePicker) findViewById(R.id.alarmTimePicker);
        alarmTextView = (TextView) findViewById(R.id.alarmText);
        ToggleButton alarmToggle = (ToggleButton) findViewById(R.id.alarmToggle);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    }


    public void onToggleClicked(View view) {
        if (((ToggleButton) view).isChecked()) {//if toggle button is "ON" do the alarming function
            Log.d("MainActivity", "Alarm On");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, alarmTimePicker.getCurrentHour());
            calendar.set(Calendar.MINUTE, alarmTimePicker.getCurrentMinute());
            Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
            pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
            alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
//In this else statement I need to add the logic so that the alarm clock stops after clicking the toggle button
        } else {//else if the toggle button is pressed again, switch off the alarm /sound
            alarmManager.cancel(pendingIntent);
            setAlarmText("");
            Log.d("MyActivity", "Alarm Off");
        }

    }

    public void setAlarmText(String alarmText) {
        alarmTextView.setText(alarmText);

    }

}

AlarmReceiver:

package com.mycompany.alarmclock;
//I haven't posted my imported stuff here, they are on my file.
import android.support.v4.content.WakefulBroadcastReceiver;

import java.net.URI;
public class AlarmReceiver extends WakefulBroadcastReceiver {
 @Override
    public void onReceive(final Context context, Intent intent) {
        MainActivity inst=MainActivity.instance();
        inst.setAlarmText("Get Up! Get up!");
        Uri alarmUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);

        if (alarmUri == null) {
            alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        }
        Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
        ringtone.play();

        //this will send a notification message
        ComponentName comp = new ComponentName(context.getPackageName(),
                AlarmService.class.getName());
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

回答1:

In your toggle button off code you can add the lines:

Uri alarmUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
ringtone.stop();

Edit:

After looking at your code, this may not work in all cases. If your activity is killed off and the alarm is fired there will be no activity open to stop the ringtone. Even starting it via the notification, the toggle button will be in the wrong state. The ringtone should probably be stopped when the notification is touched.

When the alarm fires, it calls the AlarmReceiver, which calls the AlarmService. The AlarmService is what is creating the notification. It specifies the Intent that will be called when the notification is pressed. That is your Main activity, the AlarmActivity.

PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, AlarmActivity.class), 0);

You can pass extras in the intent to notify your activity that the alarm is in the ringing state and to dismiss it then, or just set your toggle to on and let the user dismiss it.

What I don't see is a call to completeWakefulIntent(intent) which will release your wake lock, but that may be an issue with the sample.

Edit

The Ringtone needs the original instance in order to stop it. The correct way would be to create a service, but that's a bit involved for this demo. I'd suggest creating a static reference and a static method to access it.

AlarmReceiver:

    private static Ringtone mRingtone  = null;
...
    mRingtone  = RingtoneManager.getRingtone(context, alarmUri);
    mRingtone.play();
...
}

    public static void stopRingtone() {
        mRingtone.stop();
    }

AlarmActivity:

        AlarmReceiver.stopRingtone();
        alarmManager.cancel(pendingIntent);
        setAlarmText("");
        Log.d("MyActivity", "Alarm Off");