FileDocCategorySizeDatePackage
EmergencyDialer.javaAPI DocAndroid 1.5 API18154Wed May 06 22:42:46 BST 2009com.android.phone

EmergencyDialer

public class EmergencyDialer extends android.app.Activity implements android.text.TextWatcher, View.OnClickListener, View.OnKeyListener, View.OnLongClickListener
EmergencyDialer is a special dailer that is used ONLY for dialing emergency calls. It is a special case of the TwelveKeyDialer that: 1. allows ONLY emergency calls to be dialed 2. disallows voicemail functionality 3. handles keyguard access correctly NOTE: TwelveKeyDialer has been moved into the Contacts App, so the "useful" portions of the TwelveKeyDialer have been moved into this class, as part of some code cleanup.

Fields Summary
public static final String
ACTION_DIAL
private static final boolean
DBG
private static final String
LOG_TAG
private static final int
STOP_TONE
private static final int
TONE_LENGTH_MS
The length of DTMF tones in milliseconds
private static final int
TONE_RELATIVE_VOLUME
The DTMF tone volume relative to other sounds in the stream
android.widget.EditText
mDigits
private android.view.View
mDelete
private android.media.ToneGenerator
mToneGenerator
private Object
mToneGeneratorLock
private android.graphics.drawable.Drawable
mDigitsBackground
private android.graphics.drawable.Drawable
mDigitsEmptyBackground
private android.graphics.drawable.Drawable
mDeleteBackground
private android.graphics.drawable.Drawable
mDeleteEmptyBackground
private boolean
mDTMFToneEnabled
private android.content.BroadcastReceiver
mBroadcastReceiver
android.os.Handler
mToneStopper
Constructors Summary
Methods Summary
public voidafterTextChanged(android.text.Editable input)

        if (SpecialCharSequenceMgr.handleChars(this, input.toString(), this)) {
            // A special sequence was entered, clear the digits
            mDigits.getText().delete(0, mDigits.getText().length());
        }

        // Set the proper background for the dial input area
        if (mDigits.length() != 0) {
            mDelete.setBackgroundDrawable(mDeleteBackground);
            mDigits.setBackgroundDrawable(mDigitsBackground);
            mDigits.setCompoundDrawablesWithIntrinsicBounds(
                    getResources().getDrawable(R.drawable.ic_dial_number), null, null, null);
        } else {
            mDelete.setBackgroundDrawable(mDeleteEmptyBackground);
            mDigits.setBackgroundDrawable(mDigitsEmptyBackground);
            mDigits.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
        }
    
public voidbeforeTextChanged(java.lang.CharSequence s, int start, int count, int after)


              
        // Do nothing
    
private voiddisplayErrorBadNumber(java.lang.String number)
display the alert dialog

        // construct error string
        CharSequence errMsg;
        if (!TextUtils.isEmpty(number)) {
            errMsg = getString(R.string.dial_emergency_error, number);
        } else {
            errMsg = getText (R.string.dial_emergency_empty_error);
        }

        // construct dialog
        AlertDialog.Builder b = new AlertDialog.Builder(this);
        b.setTitle(getText(R.string.emergency_enable_radio_dialog_title));
        b.setMessage(errMsg);
        b.setPositiveButton(R.string.ok, null);
        b.setCancelable(true);

        // show the dialog
        AlertDialog dialog = b.create();
        dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
        dialog.show();
    
private voidkeyPressed(int keyCode)

        KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
        mDigits.onKeyDown(keyCode, event);
    
protected voidmaybeAddNumberFormatting()
Explicitly turn off number formatting, since it gets in the way of the emergency number detector

        // Do nothing.
    
public voidonClick(android.view.View view)

        final Editable digits = mDigits.getText();

        switch (view.getId()) {
            case R.id.one: {
                playTone(ToneGenerator.TONE_DTMF_1);
                keyPressed(KeyEvent.KEYCODE_1);
                return;
            }
            case R.id.two: {
                playTone(ToneGenerator.TONE_DTMF_2);
                keyPressed(KeyEvent.KEYCODE_2);
                return;
            }
            case R.id.three: {
                playTone(ToneGenerator.TONE_DTMF_3);
                keyPressed(KeyEvent.KEYCODE_3);
                return;
            }
            case R.id.four: {
                playTone(ToneGenerator.TONE_DTMF_4);
                keyPressed(KeyEvent.KEYCODE_4);
                return;
            }
            case R.id.five: {
                playTone(ToneGenerator.TONE_DTMF_5);
                keyPressed(KeyEvent.KEYCODE_5);
                return;
            }
            case R.id.six: {
                playTone(ToneGenerator.TONE_DTMF_6);
                keyPressed(KeyEvent.KEYCODE_6);
                return;
            }
            case R.id.seven: {
                playTone(ToneGenerator.TONE_DTMF_7);
                keyPressed(KeyEvent.KEYCODE_7);
                return;
            }
            case R.id.eight: {
                playTone(ToneGenerator.TONE_DTMF_8);
                keyPressed(KeyEvent.KEYCODE_8);
                return;
            }
            case R.id.nine: {
                playTone(ToneGenerator.TONE_DTMF_9);
                keyPressed(KeyEvent.KEYCODE_9);
                return;
            }
            case R.id.zero: {
                playTone(ToneGenerator.TONE_DTMF_0);
                keyPressed(KeyEvent.KEYCODE_0);
                return;
            }
            case R.id.pound: {
                playTone(ToneGenerator.TONE_DTMF_P);
                keyPressed(KeyEvent.KEYCODE_POUND);
                return;
            }
            case R.id.star: {
                playTone(ToneGenerator.TONE_DTMF_S);
                keyPressed(KeyEvent.KEYCODE_STAR);
                return;
            }
            case R.id.digits: {
                placeCall();
                return;
            }
            case R.id.backspace: {
                keyPressed(KeyEvent.KEYCODE_DEL);
                return;
            }
        }
    
protected voidonCreate(android.os.Bundle icicle)

        super.onCreate(icicle);

        // Set the content view
        setContentView(R.layout.emergency_dialer);

        // Load up the resources for the text field and delete button
        Resources r = getResources();
        mDigitsBackground = r.getDrawable(R.drawable.btn_dial_textfield_active);
        mDigitsEmptyBackground = r.getDrawable(R.drawable.btn_dial_textfield);
        mDeleteBackground = r.getDrawable(R.drawable.btn_dial_delete_active);
        mDeleteEmptyBackground = r.getDrawable(R.drawable.btn_dial_delete);

        mDigits = (EditText) findViewById(R.id.digits);
        mDigits.setKeyListener(DialerKeyListener.getInstance());
        mDigits.setOnClickListener(this);
        mDigits.setOnKeyListener(this);
        mDigits.setLongClickable(false);
        maybeAddNumberFormatting();

        // Check for the presence of the keypad
        View view = findViewById(R.id.one);
        if (view != null) {
            setupKeypad();
        }

        mDelete = findViewById(R.id.backspace);
        mDelete.setOnClickListener(this);
        mDelete.setOnLongClickListener(this);

        if (icicle != null) {
            super.onRestoreInstanceState(icicle);
        }

        // if the mToneGenerator creation fails, just continue without it.  It is
        // a local audio signal, and is not as important as the dtmf tone itself.
        synchronized (mToneGeneratorLock) {
            if (mToneGenerator == null) {
                try {
                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_RING,
                            TONE_RELATIVE_VOLUME);
                } catch (RuntimeException e) {
                    Log.w(LOG_TAG, "Exception caught while creating local tone generator: " + e);
                    mToneGenerator = null;
                }
            }
        }

        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mBroadcastReceiver, intentFilter);
    
protected voidonDestroy()

        super.onDestroy();
        synchronized (mToneGeneratorLock) {
            if (mToneGenerator != null) {
                mToneStopper.removeMessages(STOP_TONE);
                mToneGenerator.release();
                mToneGenerator = null;
            }
        }
        unregisterReceiver(mBroadcastReceiver);
    
public booleanonKey(android.view.View view, int keyCode, android.view.KeyEvent event)

        switch (view.getId()) {
            case R.id.digits:
                if (keyCode == KeyEvent.KEYCODE_ENTER) {
                    placeCall();
                    return true;
                }
                break;
        }
        return false;
    
public booleanonKeyDown(int keyCode, android.view.KeyEvent event)
handle key events

        switch (keyCode) {
            case KeyEvent.KEYCODE_CALL: {
                if (TextUtils.isEmpty(mDigits.getText().toString())) {
                    // if we are adding a call from the InCallScreen and the phone
                    // number entered is empty, we just close the dialer to expose
                    // the InCallScreen under it.
                    finish();
                } else {
                    // otherwise, we place the call.
                    placeCall();
                }
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    
public booleanonLongClick(android.view.View view)
called for long touch events

        int id = view.getId();
        switch (id) {
            case R.id.backspace: {
                mDigits.getText().delete(0, mDigits.getText().length());
                return true;
            }
            case R.id.zero: {
                keyPressed(KeyEvent.KEYCODE_PLUS);
                return true;
            }
        }
        return false;
    
public voidonPause()
turn on keyguard on pause.

        // Turn keyguard back on and set the poke lock timeout to default.  There
        // is no need to do anything with the wake lock.
        if (DBG) Log.d(LOG_TAG, "turning keyguard back on and closing the dailer");
        PhoneApp app = (PhoneApp) getApplication();
        app.reenableKeyguard();
        app.setScreenTimeout(PhoneApp.ScreenTimeoutDuration.DEFAULT);

        super.onPause();

        synchronized (mToneGeneratorLock) {
            if (mToneGenerator != null) {
                mToneStopper.removeMessages(STOP_TONE);
                mToneGenerator.release();
                mToneGenerator = null;
            }
        }
    
protected voidonPostCreate(android.os.Bundle savedInstanceState)

        super.onPostCreate(savedInstanceState);

        // This can't be done in onCreate(), since the auto-restoring of the digits
        // will play DTMF tones for all the old digits if it is when onRestoreSavedInstanceState()
        // is called. This method will be called every time the activity is created, and
        // will always happen after onRestoreSavedInstanceState().
        mDigits.addTextChangedListener(this);
    
protected voidonRestoreInstanceState(android.os.Bundle icicle)

        // Do nothing, state is restored in onCreate() if needed
    
protected voidonResume()
turn off keyguard on start.

        super.onResume();

        // retrieve the DTMF tone play back setting.
        mDTMFToneEnabled = Settings.System.getInt(getContentResolver(),
                Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;

        // if the mToneGenerator creation fails, just continue without it.  It is
        // a local audio signal, and is not as important as the dtmf tone itself.
        synchronized (mToneGeneratorLock) {
            if (mToneGenerator == null) {
                try {
                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_RING,
                            TONE_RELATIVE_VOLUME);
                } catch (RuntimeException e) {
                    Log.w(LOG_TAG, "Exception caught while creating local tone generator: " + e);
                    mToneGenerator = null;
                }
            }
        }

        // Turn keyguard off and set the poke lock timeout to medium.  There is
        // no need to do anything with the wake lock.
        if (DBG) Log.d(LOG_TAG, "turning keyguard off, set to long timeout");
        PhoneApp app = (PhoneApp) getApplication();
        app.disableKeyguard();
        app.setScreenTimeout(PhoneApp.ScreenTimeoutDuration.MEDIUM);
    
public voidonTextChanged(java.lang.CharSequence input, int start, int before, int changeCount)

        // Do nothing
    
voidplaceCall()
place the call, but check to make sure it is a viable number.

        final String number = mDigits.getText().toString();
        if (PhoneNumberUtils.isEmergencyNumber(number)) {
            if (DBG) Log.d(LOG_TAG, "placing call to " + number);

            // place the call if it is a valid number
            if (number == null || !TextUtils.isGraphic(number)) {
                // There is no number entered.
                playTone(ToneGenerator.TONE_PROP_NACK);
                return;
            }
            Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY);
            intent.setData(Uri.fromParts("tel", number, null));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
            finish();
        } else {
            if (DBG) Log.d(LOG_TAG, "rejecting bad requested number " + number);

            // erase the number and throw up an alert dialog.
            mDigits.getText().delete(0, mDigits.getText().length());
            displayErrorBadNumber(number);
        }
    
voidplayTone(int tone)
Play a tone for TONE_LENGTH_MS milliseconds.

param
tone a tone code from {@link ToneGenerator}


                       
       
        // if local tone playback is disabled, just return.
        if (!mDTMFToneEnabled) {
            return;
        }

        synchronized (mToneGeneratorLock) {
            if (mToneGenerator == null) {
                Log.w(LOG_TAG, "playTone: mToneGenerator == null, tone: " + tone);
                return;
            }

            // Remove pending STOP_TONE messages
            mToneStopper.removeMessages(STOP_TONE);

            // Start the new tone (will stop any playing tone)
            mToneGenerator.startTone(tone);
            mToneStopper.sendEmptyMessageDelayed(STOP_TONE, TONE_LENGTH_MS);
        }
    
private voidsetupKeypad()

        // Setup the listeners for the buttons
        findViewById(R.id.one).setOnClickListener(this);
        findViewById(R.id.two).setOnClickListener(this);
        findViewById(R.id.three).setOnClickListener(this);
        findViewById(R.id.four).setOnClickListener(this);
        findViewById(R.id.five).setOnClickListener(this);
        findViewById(R.id.six).setOnClickListener(this);
        findViewById(R.id.seven).setOnClickListener(this);
        findViewById(R.id.eight).setOnClickListener(this);
        findViewById(R.id.nine).setOnClickListener(this);
        findViewById(R.id.star).setOnClickListener(this);

        View view = findViewById(R.id.zero);
        view.setOnClickListener(this);
        view.setOnLongClickListener(this);

        findViewById(R.id.pound).setOnClickListener(this);