2

I am making an alarm clock which asks user to do a particular work in order to close the alarm when it rings. It is working fine but the problem is that if the user closes the alarm app from the recent activities while the alarm is ringing, the alarm stops ringing. I want that even if the user clears the app while its ringing, it should not stop ringing. It should only stop once the task given is completed. How can I implement this?

Edit #1: Activity that is called when alarm rings

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v(LOG_TAG, "in AlarmAlert");
        unlockScreen();
        setContentView(R.layout.activity_alarm_alert);

        Bundle bundle = this.getIntent().getExtras();
        alarm = (Alarm) bundle.getSerializable("alarm");
        alarmDatabase = new AlarmDatabase(this);

        //Uri uri = alarm.getRingtonePath();
        question = (TextView)findViewById(R.id.question);
        answer = (TextView) findViewById(R.id.answer);

        oldColors =  answer.getTextColors();
        diff = alarm.getDifficulty().toString();
        questionString = GenerateMathsQuestion.generateQuestion(diff);
        question.setText(questionString);
        actualAnswer = EvaluateString.evaluate(questionString);
        AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

        int result = am.requestAudioFocus(focusChangeListener,
               AudioManager.STREAM_MUSIC,
               AudioManager.AUDIOFOCUS_GAIN);

        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setVolume(1.0f, 1.0f);
            mediaPlayer.setLooping(true);
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);

            try {
                mediaPlayer.setDataSource(this,   Uri.parse(alarm.getRingtonePath()));
                mediaPlayer.prepare();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mediaPlayer.start();
        }

        if(alarm.getIsVibrate()) {
            vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
            long[] pattern = {1000, 200, 200, 200};
            vibrator.vibrate(pattern, 0);
        }
    }

public void closeAlarm(){
        Log.v(LOG_TAG, "will now stop");
        mediaPlayer.stop();
        if(vibrator!=null)
            vibrator.cancel();
        Log.v(LOG_TAG, "will now release");
        mediaPlayer.release();
        Log.v(LOG_TAG, "id of ringing alarm: " + alarm.getAlarmId());
        alarm.setIsActive(false);
        alarmDatabase.updateData(alarm);
        cursor = alarmDatabase.sortQuery();
        while(cursor.moveToNext()){
            int id = cursor.getInt(cursor.getColumnIndex(AlarmDatabase.COLUMN_UID));
            currentAlarm = alarmDatabase.getAlarm(id);
            Log.v(LOG_TAG, "id of next alarm " + id);
            if(currentAlarm != null) {
                if (currentAlarm.getIsActive() == true) {
                    currentAlarm.scheduleAlarm(this, true);
                    break;
                }
            }
        }
        this.finish();
    }
Priyanshu Goyal
  • 332
  • 4
  • 17

1 Answers1

1

You should use Services. Take a look at it, that is what you want it. Generally you can make it to run an operation, and a service wont return any result. But it runs indefinitely even when you kill the app from task manager or free RAM.

I suggest this tutorial for reading about services.

UPDATE

Implement your activity with the service in the following way so it can talk with the layout and stops the alarm when required.

public class HelloService extends Service {
  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;

  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          // Normally we would do some work here, like download a file.
          // For our sample, we just sleep for 5 seconds.
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              // Restore interrupt status.
              Thread.currentThread().interrupt();
          }
          // Stop the service using the startId, so that we don't stop
          // the service in the middle of handling another job
          stopSelf(msg.arg1);
      }
  }

  @Override
  public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    // Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);

      // If we get killed, after returning from here, restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }

  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
  }
}
Sibidharan
  • 2,717
  • 2
  • 26
  • 54
  • But I have a layout that needs to be associated with it. So, basically at the moment, my broadcast receiver calls an activity which is assciated with a layout. What change should I make? – Priyanshu Goyal Apr 30 '16 at 17:26