0

I have done research to try to get an alert Dialog outside of my application, but nothing makes sense to me (I am a beginner in Android). I am using a basic timer in my app, I want the user to be able to set the timer, then leave the app if they want to, and when the timer finishes, it pops up on the screen wherever they may be.

Right now I can get the alert Dialog to show up within an activity. But if you go to the home screen and the timer ends, the dialog does not show up there. Any ideas how to get it to show outside of the app? Do I need to put this alert Dialog code into its own class (instead of inside another activity of the app, where it is now)?

Here is the code for the alert Dialog. The alert is in the timerDone() method, 3rd method from the bottom.

ZombieThemedActivity.java

package com.azurespot.disastertimer.app.themedactivities;

import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.azurespot.disastertimer.app.MainSelectorActivity.OnMediaPlayerUpdatedListener;
import com.azurespot.disastertimer.app.MainSelectorActivity;
import com.azurespot.disastertimer.app.R;

public class ZombieThemedActivity extends ActionBarActivity implements OnMediaPlayerUpdatedListener {

    long start_time_seconds;  //time user enters into timer in seconds (passed from main activity)
    long remaining_time, remaining_time_paused;  //keeps track of remaining time on timer
    Boolean is_paused;  //keeps track if timer is paused or not (to pause or restart timer)
    TextView mTextField;
    private CountDownTimer timer;
    public MediaPlayer zombieDone;

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

        MainSelectorActivity.setOnMediaPlayerUpdatedListener(ZombieThemedActivity.this);

        // The time in seconds from number picker that was send with the intent
        Bundle bTimeSetSec = getIntent().getExtras();  // need to pass variable as a bundle !!!
        start_time_seconds = bTimeSetSec.getInt("timeSetSecZ");
        is_paused = false;
        Log.i("DT", "Time is " + start_time_seconds + " in seconds  Z");
        SetUpTimer();
        // Creates a visible pause button in themed activities, until toggle code
        // in the PauseTimer() click method can take over
        findViewById(R.id.btnPause).setBackgroundResource(R.drawable.ic_timer_pause);
    }

       // Interface
    @Override
    public void onMediaPlayerStopped() {
        zombieDone.stop();
        timer.cancel();
    }

    // This is a basic timer, but it counts down from time given
    // Can maybe put a button click listener for pause, reset and save the millisUntilFinished
    public void SetUpTimer() {
        mTextField = (TextView) findViewById(R.id.txTimeCounting);
        if (is_paused) {
            // if pause button was hit then, stay on this screen, but use remaining time, not start time.
            start_time_seconds = remaining_time_paused;
            Log.i("DT","Is Paused state = " + is_paused);
        }

        timer = new CountDownTimer(start_time_seconds*1000, 1000) {
            // since timer needs millisUntilFinished... the max of a long is 9223372036854775807seconds
            public void onTick(long millisUntilFinished) {

                // Convert seconds to hr/min/sec for message
                // since millisUntilFinished is a long (>3billion) and modulus (%) is for ints, need to put a L at the end to tell it the number is literal and somehow allow ints.
                remaining_time = millisUntilFinished/1000;

                // Math.floor - will just get the opposite of the modulus (name?), requires double input.
                // casting double -> int will result in getting rid of decimal (great, we don't have one!)
                double remaining_time_double = (int)remaining_time;
                int mHr = (int) Math.floor(remaining_time_double / 3600);
                int mMin = (int) Math.floor((remaining_time_double-(3600*mHr)) / 60);
                int mSec = (int) Math.floor(remaining_time_double-(3600*mHr)-(60*mMin));

                // Convert int to string (and add a zero in front of int tht are <10 for looks
                String smHr;
                String smMin;
                String smSec;
                if (mHr < 10) {smHr = "0" + Integer.toString(mHr); } else { smHr = String.valueOf(mHr); }
                if (mMin < 10) { smMin = "0" + String.valueOf(mMin); } else { smMin = String.valueOf(mMin); }
                if (mSec < 10) { smSec = "0" + String.valueOf(mSec); } else { smSec = String.valueOf(mSec); }

                Log.i("DT", "time is: " + smHr + ":" + smMin + ":" + smSec);
                mTextField.setText(smHr + ":" + smMin + ":" + smSec);
                // mTextField.setText(millisUntilFinished/1000 + " seconds");

                if(millisUntilFinished <= 10000)
                    mTextField.setTextColor(Color.RED);
                // if less than 10seconds make text red!
            }

            public void onFinish() {
                mTextField.setText("BRAINS!!");
                // call some media function here
                MediaPlayer mp = MediaPlayer.create(ZombieThemedActivity.this, R.raw.zombie_sound);
                mp.start();
                zombieDone = mp;

                // This disables the pause/play button when timer ends
                Button disablePausePlay = (Button)findViewById(R.id.btnPause);
                disablePausePlay.setEnabled(false);
                timerDone();
            }
        };
        timer.start();
    }


    public void PauseTimer (View v) {

        // Dynamically creates the toggled buttons (without any xml)
        switch(v.getId()){
            case R.id.btnPause:

                if(!is_paused){
                    // Removes set pause button from onCreate, and replaces with new one
                    v.setBackgroundResource(0);
                    v.setBackgroundResource(R.drawable.ic_timer_play);
                }
                else{
                    v.setBackgroundResource(R.drawable.ic_timer_pause);
                }
        }

        // do something when the pause button is hit
        // set IS_PAUSED to false (so when timer is called, it uses remaining time instead of start time.
        // cancels current timer - set the time to display the paused time, re-labels the button to "Re-Start"

        if (!is_paused) {

            remaining_time_paused = remaining_time;

            double paused_time = remaining_time_paused;
            int mHr = (int) Math.floor(paused_time / 3600);
            int mMin = (int) Math.floor((paused_time-(3600*mHr)) / 60);
            int mSec = (int) Math.floor(paused_time-(3600*mHr)-(60*mMin));
            // Convert int to string (and add a zero in front of int tht are <10 for looks
            String smHr;
            String smMin;
            String smSec;
            if (mHr < 10) {smHr = "0" + Integer.toString(mHr); } else { smHr = String.valueOf(mHr); }
            if (mMin < 10) { smMin = "0" + String.valueOf(mMin); } else { smMin = String.valueOf(mMin); }
            if (mSec < 10) { smSec = "0" + String.valueOf(mSec); } else { smSec = String.valueOf(mSec); }

            // set the timer
            Log.d("DT", "time is: " + smHr + ":" + smMin + ":" + smSec);
            mTextField.setText(smHr + ":" + smMin + ":" + smSec);
            is_paused = true;
            timer.cancel();
            Log.d("DT", "is paused hit yes, remaining time is " + remaining_time);
        }
        else {
            SetUpTimer();
            is_paused = false;   // must reset the pause state AFTER calling the timer method
        }
    }

    // This overrides the onPause() method so when back button is pressed,
    // the music file stops and releases from memory, which means the object is gone

    @Override
    protected void onPause(){
        super.onPause();
        if (zombieDone != null) //add a null check here
        {
            if (zombieDone.isPlaying()) {
                zombieDone.stop();
                zombieDone.release();
            // If this does nothing then the else is not needed
            } else {
                // Do nothing
            }
        }
    }

    public void ReturnToTimerScreen (View v) {
        // RESET button is hit !!!!
        // returns to first screen for selection of new time, must cancel timer
        timer.cancel();
        Intent iReset = new Intent(getBaseContext(), MainSelectorActivity.class);
        startActivity(iReset);
        Log.i("DT", "RESET button was hit");
    }

    public void timerDone() {

        // Create custom dialog object
        final Dialog dialog = new Dialog(ZombieThemedActivity.this);
        // Include alert_popup.xml file
        dialog.setContentView(R.layout.alert_popup);
        // Set dialog title
        dialog.setTitle("BRAINS!!!");
        ImageView image = (ImageView) dialog.findViewById(R.id.imageView01);
        image.setImageResource(R.drawable.ic_launcher_nuke);

        dialog.show();

        Button declineButton = (Button) dialog.findViewById(R.id.okbutton);
        // if decline button is clicked, close the custom dialog
        declineButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Close dialog
                dialog.dismiss();
                timer.cancel();
                zombieDone.stop();
                zombieDone.release();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.zombie_themed, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
Azurespot
  • 3,066
  • 3
  • 45
  • 73
  • 1
    things like these are achieved via a Notification not via an AlertDialog. You can notify the user using NotificationManager when the timer runs out. Then, onCLick of it, you can launch an activity or so. – Atish Agrawal May 23 '14 at 05:58
  • Oh interesting. And I can make an alert box for this notification as well? We have to have some kind of pop up graphic show up where the user can press "ok" and the alarm shuts off. – Azurespot May 23 '14 at 06:00
  • 1
    Ya you can do this in Notification bar also, it is better in this case I think Noni – Pratik Dasa May 23 '14 at 06:03
  • The answer is in this thread: http://stackoverflow.com/questions/2147144/android-how-to-display-a-dialog-over-a-native-screen – Mayank Saini May 23 '14 at 06:08
  • Thanks Mayank, so does this mean that link page expects me to have the Dialog (or I should probably use AlertDialog) in its own Activity or class? Then I simply add that code to the Manifest and that's it? – Azurespot May 23 '14 at 06:14
  • You should use a Dialog instead. – Mayank Saini May 23 '14 at 07:00

1 Answers1

0

If you want to send messages outside of the application, you have to use NotificationManager.

I suggest you take a look this tutorial: http://www.vogella.com/tutorials/AndroidNotifications/article.html

CanDroid
  • 633
  • 6
  • 15
  • Thanks CanDroid, I am going to try this and if I can get it to work, I will check your response as the right answer, if I can. – Azurespot May 23 '14 at 06:14
  • Hello Noni, thanks. I also don't know how you can check my answer as the right answer. :) – CanDroid May 23 '14 at 06:42
  • Darn, this tutorial gives a runtime error: `java.lang.IllegalArgumentException: eglChooseConfig failed EGL_NOT_INITIALIZED`, but I don't understand why. Can't find info on this error anywhere. – Azurespot May 23 '14 at 06:56
  • Actually, that error was from not restarting my emulator after switching to a new project. I restarted it, and got the tutorial app to run, but now the button is clicked and nothing happens. I will keep working on it. – Azurespot May 23 '14 at 07:11
  • I made an application and used Notification Manager also. I was tried many times. :) I know that Vogella's tutorial is working, you can solve it soon. :) – CanDroid May 23 '14 at 07:30
  • Thanks CanDroid. I don't think it explains things completely, I am a beginner, so I maybe have left something out if he did not tell me to do something exactly. :( I followed all the steps and I get the button, but clicking it does nothing. And I don't see how this is supposed to show notifications outside of an activity. Too confusing. – Azurespot May 23 '14 at 07:59