1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.ui; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.content.ContentValues; 22 import android.content.DialogInterface; 23 import android.content.DialogInterface.OnClickListener; 24 import android.content.Intent; 25 import android.os.Bundle; 26 import android.os.Handler; 27 import android.os.Message; 28 import android.os.SystemClock; 29 import android.provider.Telephony.Sms; 30 import android.text.TextUtils; 31 import android.util.Log; 32 import android.view.Window; 33 34 import com.android.messaging.R; 35 import com.android.messaging.datamodel.action.ReceiveSmsMessageAction; 36 import com.android.messaging.util.Assert; 37 38 import java.util.ArrayList; 39 40 /** 41 * Display a class-zero SMS message to the user. Wait for the user to dismiss 42 * it. 43 */ 44 public class ClassZeroActivity extends Activity { 45 private static final boolean VERBOSE = false; 46 private static final String TAG = "display_00"; 47 private static final int ON_AUTO_SAVE = 1; 48 49 /** Default timer to dismiss the dialog. */ 50 private static final long DEFAULT_TIMER = 5 * 60 * 1000; 51 52 /** To remember the exact time when the timer should fire. */ 53 private static final String TIMER_FIRE = "timer_fire"; 54 55 private ContentValues mMessageValues = null; 56 57 /** Is the message read. */ 58 private boolean mRead = false; 59 60 /** The timer to dismiss the dialog automatically. */ 61 private long mTimerSet = 0; 62 private AlertDialog mDialog = null; 63 64 private ArrayList<ContentValues> mMessageQueue = null; 65 66 private final Handler mHandler = new Handler() { 67 @Override 68 public void handleMessage(final Message msg) { 69 // Do not handle an invalid message. 70 if (msg.what == ON_AUTO_SAVE) { 71 mRead = false; 72 mDialog.dismiss(); 73 saveMessage(); 74 processNextMessage(); 75 } 76 } 77 }; 78 queueMsgFromIntent(final Intent msgIntent)79 private boolean queueMsgFromIntent(final Intent msgIntent) { 80 final ContentValues messageValues = 81 msgIntent.getParcelableExtra(UIIntents.UI_INTENT_EXTRA_MESSAGE_VALUES); 82 // that takes the format argument is a hidden API right now. 83 final String message = messageValues.getAsString(Sms.BODY); 84 if (TextUtils.isEmpty(message)) { 85 if (mMessageQueue.size() == 0) { 86 finish(); 87 } 88 return false; 89 } 90 mMessageQueue.add(messageValues); 91 return true; 92 } 93 processNextMessage()94 private void processNextMessage() { 95 if (mMessageQueue.size() > 0) { 96 mMessageQueue.remove(0); 97 } 98 if (mMessageQueue.size() == 0) { 99 finish(); 100 } else { 101 displayZeroMessage(mMessageQueue.get(0)); 102 } 103 } 104 saveMessage()105 private void saveMessage() { 106 mMessageValues.put(Sms.Inbox.READ, mRead ? Integer.valueOf(1) : Integer.valueOf(0)); 107 final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(mMessageValues); 108 action.start(); 109 } 110 111 @Override onCreate(final Bundle icicle)112 protected void onCreate(final Bundle icicle) { 113 super.onCreate(icicle); 114 requestWindowFeature(Window.FEATURE_NO_TITLE); 115 116 if (mMessageQueue == null) { 117 mMessageQueue = new ArrayList<ContentValues>(); 118 } 119 if (!queueMsgFromIntent(getIntent())) { 120 return; 121 } 122 Assert.isTrue(mMessageQueue.size() == 1); 123 if (mMessageQueue.size() == 1) { 124 displayZeroMessage(mMessageQueue.get(0)); 125 } 126 127 if (icicle != null) { 128 mTimerSet = icicle.getLong(TIMER_FIRE, mTimerSet); 129 } 130 } 131 displayZeroMessage(final ContentValues messageValues)132 private void displayZeroMessage(final ContentValues messageValues) { 133 /* This'll be used by the save action */ 134 mMessageValues = messageValues; 135 final String message = messageValues.getAsString(Sms.BODY);; 136 137 mDialog = new AlertDialog.Builder(this).setMessage(message) 138 .setPositiveButton(R.string.save, mSaveListener) 139 .setNegativeButton(android.R.string.cancel, mCancelListener) 140 .setTitle(R.string.class_0_message_activity) 141 .setCancelable(false).show(); 142 final long now = SystemClock.uptimeMillis(); 143 mTimerSet = now + DEFAULT_TIMER; 144 } 145 146 @Override onNewIntent(final Intent msgIntent)147 protected void onNewIntent(final Intent msgIntent) { 148 // Running with another visible message, queue this one 149 queueMsgFromIntent(msgIntent); 150 } 151 152 @Override onStart()153 protected void onStart() { 154 super.onStart(); 155 final long now = SystemClock.uptimeMillis(); 156 if (mTimerSet <= now) { 157 // Save the message if the timer already expired. 158 mHandler.sendEmptyMessage(ON_AUTO_SAVE); 159 } else { 160 mHandler.sendEmptyMessageAtTime(ON_AUTO_SAVE, mTimerSet); 161 if (VERBOSE) { 162 Log.d(TAG, "onRestart time = " + Long.toString(mTimerSet) + " " 163 + this.toString()); 164 } 165 } 166 } 167 168 @Override onSaveInstanceState(final Bundle outState)169 protected void onSaveInstanceState(final Bundle outState) { 170 super.onSaveInstanceState(outState); 171 outState.putLong(TIMER_FIRE, mTimerSet); 172 if (VERBOSE) { 173 Log.d(TAG, "onSaveInstanceState time = " + Long.toString(mTimerSet) 174 + " " + this.toString()); 175 } 176 } 177 178 @Override onStop()179 protected void onStop() { 180 super.onStop(); 181 mHandler.removeMessages(ON_AUTO_SAVE); 182 if (VERBOSE) { 183 Log.d(TAG, "onStop time = " + Long.toString(mTimerSet) 184 + " " + this.toString()); 185 } 186 } 187 188 private final OnClickListener mCancelListener = new OnClickListener() { 189 @Override 190 public void onClick(final DialogInterface dialog, final int whichButton) { 191 dialog.dismiss(); 192 processNextMessage(); 193 } 194 }; 195 196 private final OnClickListener mSaveListener = new OnClickListener() { 197 @Override 198 public void onClick(final DialogInterface dialog, final int whichButton) { 199 mRead = true; 200 saveMessage(); 201 dialog.dismiss(); 202 processNextMessage(); 203 } 204 }; 205 } 206