blob: 126e7376c9cac3699b92d33b1432ae20ea1d640d [file] [log] [blame]
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mms.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Telephony.Sms;
import android.provider.Telephony.Sms.Inbox;
import android.telephony.SmsMessage;
import android.text.TextUtils;
import android.util.Log;
import android.view.Window;
import com.android.mms.R;
import com.android.mms.transaction.MessagingNotification;
import java.util.ArrayList;
/**
* Display a class-zero SMS message to the user. Wait for the user to dismiss
* it.
*/
public class ClassZeroActivity extends Activity {
private static final String BUFFER = " ";
private static final int BUFFER_OFFSET = BUFFER.length() * 2;
private static final String TAG = "display_00";
private static final int ON_AUTO_SAVE = 1;
private static final String[] REPLACE_PROJECTION = new String[] { Sms._ID,
Sms.ADDRESS, Sms.PROTOCOL };
private static final int REPLACE_COLUMN_ID = 0;
/** Default timer to dismiss the dialog. */
private static final long DEFAULT_TIMER = 5 * 60 * 1000;
/** To remember the exact time when the timer should fire. */
private static final String TIMER_FIRE = "timer_fire";
private SmsMessage mMessage = null;
/** Is the message read. */
private boolean mRead = false;
/** The timer to dismiss the dialog automatically. */
private long mTimerSet = 0;
private AlertDialog mDialog = null;
private ArrayList<SmsMessage> mMessageQueue = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Do not handle an invalid message.
if (msg.what == ON_AUTO_SAVE) {
mRead = false;
mDialog.dismiss();
saveMessage();
processNextMessage();
}
}
};
private boolean queueMsgFromIntent(Intent msgIntent) {
byte[] pdu = msgIntent.getByteArrayExtra("pdu");
String format = msgIntent.getStringExtra("format");
SmsMessage rawMessage = SmsMessage.createFromPdu(pdu, format);
String message = rawMessage.getMessageBody();
if (TextUtils.isEmpty(message)) {
if (mMessageQueue.size() == 0) {
finish();
}
return false;
}
mMessageQueue.add(rawMessage);
return true;
}
private void processNextMessage() {
mMessageQueue.remove(0);
if (mMessageQueue.size() == 0) {
finish();
} else {
displayZeroMessage(mMessageQueue.get(0));
}
}
private void saveMessage() {
Uri messageUri = null;
if (mMessage.isReplace()) {
messageUri = replaceMessage(mMessage);
} else {
messageUri = storeMessage(mMessage);
}
if (!mRead && messageUri != null) {
MessagingNotification.nonBlockingUpdateNewMessageIndicator(
this,
MessagingNotification.THREAD_ALL, // always notify on class-zero msgs
false);
}
}
@Override
protected void onNewIntent(Intent msgIntent) {
/* Running with another visible message, queue this one */
queueMsgFromIntent(msgIntent);
}
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setBackgroundDrawableResource(
R.drawable.class_zero_background);
if (mMessageQueue == null) {
mMessageQueue = new ArrayList<SmsMessage>();
}
if (!queueMsgFromIntent(getIntent())) {
return;
}
if (mMessageQueue.size() == 1) {
displayZeroMessage(mMessageQueue.get(0));
}
if (icicle != null) {
mTimerSet = icicle.getLong(TIMER_FIRE, mTimerSet);
}
}
private void displayZeroMessage(SmsMessage rawMessage) {
String message = rawMessage.getMessageBody();
/* This'll be used by the save action */
mMessage = rawMessage;
mDialog = new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_DARK).setMessage(message)
.setPositiveButton(R.string.save, mSaveListener)
.setNegativeButton(android.R.string.cancel, mCancelListener)
.setCancelable(false).show();
long now = SystemClock.uptimeMillis();
mTimerSet = now + DEFAULT_TIMER;
}
@Override
protected void onStart() {
super.onStart();
long now = SystemClock.uptimeMillis();
if (mTimerSet <= now) {
// Save the message if the timer already expired.
mHandler.sendEmptyMessage(ON_AUTO_SAVE);
} else {
mHandler.sendEmptyMessageAtTime(ON_AUTO_SAVE, mTimerSet);
if (false) {
Log.d(TAG, "onRestart time = " + Long.toString(mTimerSet) + " "
+ this.toString());
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong(TIMER_FIRE, mTimerSet);
if (false) {
Log.d(TAG, "onSaveInstanceState time = " + Long.toString(mTimerSet)
+ " " + this.toString());
}
}
@Override
protected void onStop() {
super.onStop();
mHandler.removeMessages(ON_AUTO_SAVE);
if (false) {
Log.d(TAG, "onStop time = " + Long.toString(mTimerSet)
+ " " + this.toString());
}
}
private final OnClickListener mCancelListener = new OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
processNextMessage();
}
};
private final OnClickListener mSaveListener = new OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mRead = true;
saveMessage();
dialog.dismiss();
processNextMessage();
}
};
private ContentValues extractContentValues(SmsMessage sms) {
// Store the message in the content provider.
ContentValues values = new ContentValues();
values.put(Inbox.ADDRESS, sms.getDisplayOriginatingAddress());
// Use now for the timestamp to avoid confusion with clock
// drift between the handset and the SMSC.
values.put(Inbox.DATE, new Long(System.currentTimeMillis()));
values.put(Inbox.PROTOCOL, sms.getProtocolIdentifier());
values.put(Inbox.READ, Integer.valueOf(mRead ? 1 : 0));
values.put(Inbox.SEEN, Integer.valueOf(mRead ? 1 : 0));
if (sms.getPseudoSubject().length() > 0) {
values.put(Inbox.SUBJECT, sms.getPseudoSubject());
}
values.put(Inbox.REPLY_PATH_PRESENT, sms.isReplyPathPresent() ? 1 : 0);
values.put(Inbox.SERVICE_CENTER, sms.getServiceCenterAddress());
return values;
}
private Uri replaceMessage(SmsMessage sms) {
ContentValues values = extractContentValues(sms);
values.put(Inbox.BODY, sms.getMessageBody());
ContentResolver resolver = getContentResolver();
String originatingAddress = sms.getOriginatingAddress();
int protocolIdentifier = sms.getProtocolIdentifier();
String selection = Sms.ADDRESS + " = ? AND " + Sms.PROTOCOL + " = ?";
String[] selectionArgs = new String[] { originatingAddress,
Integer.toString(protocolIdentifier) };
Cursor cursor = SqliteWrapper.query(this, resolver, Inbox.CONTENT_URI,
REPLACE_PROJECTION, selection, selectionArgs, null);
try {
if (cursor.moveToFirst()) {
long messageId = cursor.getLong(REPLACE_COLUMN_ID);
Uri messageUri = ContentUris.withAppendedId(
Sms.CONTENT_URI, messageId);
SqliteWrapper.update(this, resolver, messageUri, values,
null, null);
return messageUri;
}
} finally {
cursor.close();
}
return storeMessage(sms);
}
private Uri storeMessage(SmsMessage sms) {
// Store the message in the content provider.
ContentValues values = extractContentValues(sms);
values.put(Inbox.BODY, sms.getDisplayMessageBody());
ContentResolver resolver = getContentResolver();
if (false) {
Log.d(TAG, "storeMessage " + this.toString());
}
return SqliteWrapper.insert(this, resolver, Inbox.CONTENT_URI, values);
}
}