Home | History | Annotate | Download | only in cellbroadcastreceiver
      1 /*
      2  * Copyright (C) 2011 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.cellbroadcastreceiver;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.ListActivity;
     21 import android.app.NotificationManager;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.content.DialogInterface.OnClickListener;
     25 import android.content.Intent;
     26 import android.database.Cursor;
     27 import android.database.sqlite.SQLiteDatabase;
     28 import android.os.Bundle;
     29 import android.view.ContextMenu;
     30 import android.view.ContextMenu.ContextMenuInfo;
     31 import android.view.Menu;
     32 import android.view.MenuItem;
     33 import android.view.View;
     34 import android.view.View.OnCreateContextMenuListener;
     35 import android.widget.ListView;
     36 import android.widget.TextView;
     37 
     38 /**
     39  * This activity provides a list view of received cell broadcasts.
     40  */
     41 public class CellBroadcastListActivity extends ListActivity {
     42     private static final String TAG = "CellBroadcastListActivity";
     43 
     44     // IDs of the main menu items.
     45     public static final int MENU_DELETE_ALL           = 3;
     46     public static final int MENU_PREFERENCES          = 4;
     47 
     48     // IDs of the context menu items for the list of broadcasts.
     49     public static final int MENU_DELETE               = 0;
     50     public static final int MENU_VIEW                 = 1;
     51 
     52     private CellBroadcastListAdapter mListAdapter;
     53 
     54     private SQLiteDatabase mBroadcastDb;
     55 
     56     private Cursor mAdapterCursor;
     57 
     58     @Override
     59     protected void onCreate(Bundle savedInstanceState) {
     60         super.onCreate(savedInstanceState);
     61         setContentView(R.layout.cell_broadcast_list_screen);
     62 
     63         ListView listView = getListView();
     64         listView.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
     65 
     66         if (mBroadcastDb == null) {
     67             CellBroadcastDatabase.DatabaseHelper helper =
     68                     new CellBroadcastDatabase.DatabaseHelper(this);
     69             mBroadcastDb = helper.getReadableDatabase();
     70         }
     71 
     72         if (mAdapterCursor == null) {
     73             mAdapterCursor = CellBroadcastDatabase.getCursor(mBroadcastDb);
     74         }
     75 
     76         mListAdapter = new CellBroadcastListAdapter(this, mAdapterCursor);
     77         setListAdapter(mListAdapter);
     78 
     79         CellBroadcastDatabaseService.setActiveListActivity(this);
     80 
     81         parseIntent(getIntent());
     82     }
     83 
     84     @Override
     85     protected void onDestroy() {
     86         if (mAdapterCursor != null) {
     87             mAdapterCursor.close();
     88             mAdapterCursor = null;
     89         }
     90         if (mBroadcastDb != null) {
     91             mBroadcastDb.close();
     92             mBroadcastDb = null;
     93         }
     94         CellBroadcastDatabaseService.setActiveListActivity(null);
     95         super.onDestroy();
     96     }
     97 
     98     /** Callback from CellBroadcastDatabaseService after content changes. */
     99     void databaseContentChanged() {
    100         runOnUiThread(new Runnable() {
    101             public void run() {
    102                 mAdapterCursor.requery();
    103             }
    104         });
    105     }
    106 
    107     @Override
    108     protected void onNewIntent(Intent intent) {
    109         // TODO: how do multiple messages stack together?
    110         // removeDialog(DIALOG_SHOW_MESSAGE);
    111         parseIntent(intent);
    112     }
    113 
    114     @Override
    115     public boolean onPrepareOptionsMenu(Menu menu) {
    116         menu.clear();
    117 
    118         if (mListAdapter.getCount() > 0) {
    119             menu.add(0, MENU_DELETE_ALL, 0, R.string.menu_delete_all).setIcon(
    120                     android.R.drawable.ic_menu_delete);
    121         }
    122 
    123         menu.add(0, MENU_PREFERENCES, 0, R.string.menu_preferences).setIcon(
    124                 android.R.drawable.ic_menu_preferences);
    125 
    126         return true;
    127     }
    128 
    129     @Override
    130     public boolean onOptionsItemSelected(MenuItem item) {
    131         switch(item.getItemId()) {
    132             case MENU_DELETE_ALL:
    133                 confirmDeleteThread(-1);
    134                 break;
    135 
    136             case MENU_PREFERENCES:
    137                 Intent intent = new Intent(this, CellBroadcastSettings.class);
    138                 startActivityIfNeeded(intent, -1);
    139                 break;
    140 
    141             default:
    142                 return true;
    143         }
    144         return false;
    145     }
    146 
    147     @Override
    148     protected void onListItemClick(ListView l, View v, int position, long id) {
    149         Cursor cursor = mListAdapter.getCursor();
    150         if (cursor != null && cursor.getPosition() >= 0) {
    151             showDialogAndMarkRead(cursor);
    152         }
    153     }
    154 
    155     private final OnCreateContextMenuListener mOnCreateContextMenuListener =
    156             new OnCreateContextMenuListener() {
    157                 public void onCreateContextMenu(ContextMenu menu, View v,
    158                         ContextMenuInfo menuInfo) {
    159                     menu.add(0, MENU_VIEW, 0, R.string.menu_view);
    160                     menu.add(0, MENU_DELETE, 0, R.string.menu_delete);
    161                 }
    162             };
    163 
    164     @Override
    165     public boolean onContextItemSelected(MenuItem item) {
    166         Cursor cursor = mListAdapter.getCursor();
    167         if (cursor != null && cursor.getPosition() >= 0) {
    168             switch (item.getItemId()) {
    169                 case MENU_DELETE:
    170                     confirmDeleteThread(cursor.getLong(CellBroadcastDatabase.COLUMN_ID));
    171                     break;
    172 
    173                 case MENU_VIEW:
    174                     showDialogAndMarkRead(cursor);
    175                     break;
    176 
    177                 default:
    178                     break;
    179             }
    180         }
    181         return super.onContextItemSelected(item);
    182     }
    183 
    184     private void showDialogAndMarkRead(Cursor cursor) {
    185         CellBroadcastMessage cbm = CellBroadcastMessage.createFromCursor(cursor);
    186         boolean isAlertMessage = cbm.isPublicAlertMessage() || CellBroadcastConfigService
    187                 .isOperatorDefinedEmergencyId(cbm.getMessageIdentifier());
    188         // show emergency alerts with the warning icon, but don't play alert tone
    189         CellBroadcastAlertDialog dialog = new CellBroadcastAlertDialog(this,
    190                 cbm.getDialogTitleResource(), cbm.getMessageBody(),
    191                 isAlertMessage, cbm.getDeliveryTime());
    192         dialog.show();
    193     }
    194 
    195     /**
    196      * Start the process of putting up a dialog to confirm deleting a broadcast.
    197      * @param rowId the row ID of the broadcast to delete, or -1 to delete all broadcasts
    198      */
    199     public void confirmDeleteThread(long rowId) {
    200         DeleteThreadListener listener = new DeleteThreadListener(rowId);
    201         confirmDeleteThreadDialog(listener, (rowId == -1), this);
    202     }
    203 
    204     /**
    205      * Build and show the proper delete broadcast dialog. The UI is slightly different
    206      * depending on whether there are locked messages in the thread(s) and whether we're
    207      * deleting a single broadcast or all broadcasts.
    208      * @param listener gets called when the delete button is pressed
    209      * @param deleteAll whether to show a single thread or all threads UI
    210      * @param context used to load the various UI elements
    211      */
    212     public static void confirmDeleteThreadDialog(DeleteThreadListener listener,
    213             boolean deleteAll, Context context) {
    214         View contents = View.inflate(context, R.layout.delete_broadcast_dialog_view, null);
    215         TextView msg = (TextView)contents.findViewById(R.id.message);
    216         msg.setText(deleteAll
    217                 ? R.string.confirm_delete_all_broadcasts
    218                         : R.string.confirm_delete_broadcast);
    219 
    220         AlertDialog.Builder builder = new AlertDialog.Builder(context);
    221         builder.setTitle(R.string.confirm_dialog_title)
    222             .setIcon(android.R.drawable.ic_dialog_alert)
    223         .setCancelable(true)
    224         .setPositiveButton(R.string.button_delete, listener)
    225         .setNegativeButton(R.string.button_cancel, null)
    226         .setView(contents)
    227         .show();
    228     }
    229 
    230     public class DeleteThreadListener implements OnClickListener {
    231         private final long mRowId;
    232 
    233         public DeleteThreadListener(long rowId) {
    234             mRowId = rowId;
    235         }
    236 
    237         public void onClick(DialogInterface dialog, int whichButton) {
    238             if (mRowId != -1) {
    239                 // delete from database on a separate service thread
    240                 Intent dbWriteIntent = new Intent(CellBroadcastListActivity.this,
    241                         CellBroadcastDatabaseService.class);
    242                 dbWriteIntent.setAction(CellBroadcastDatabaseService.ACTION_DELETE_BROADCAST);
    243                 dbWriteIntent.putExtra(CellBroadcastDatabaseService.DATABASE_ROW_ID_EXTRA, mRowId);
    244                 startService(dbWriteIntent);
    245             } else {
    246                 // delete from database on a separate service thread
    247                 Intent dbWriteIntent = new Intent(CellBroadcastListActivity.this,
    248                         CellBroadcastDatabaseService.class);
    249                 dbWriteIntent.setAction(CellBroadcastDatabaseService.ACTION_DELETE_ALL_BROADCASTS);
    250                 startService(dbWriteIntent);
    251             }
    252             dialog.dismiss();
    253         }
    254     }
    255 
    256     private void parseIntent(Intent intent) {
    257         if (intent == null) {
    258             return;
    259         }
    260         Bundle extras = intent.getExtras();
    261         if (extras == null) {
    262             return;
    263         }
    264 
    265         CellBroadcastMessage cbm = extras.getParcelable(CellBroadcastMessage.SMS_CB_MESSAGE_EXTRA);
    266         int notificationId = extras.getInt(CellBroadcastAlertService.SMS_CB_NOTIFICATION_ID_EXTRA);
    267 
    268         // Dismiss the notification that brought us here.
    269         NotificationManager notificationManager =
    270             (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
    271         notificationManager.cancel(notificationId);
    272 
    273         boolean isEmergencyAlert = cbm.isPublicAlertMessage() || CellBroadcastConfigService
    274                 .isOperatorDefinedEmergencyId(cbm.getMessageIdentifier());
    275 
    276         CellBroadcastAlertDialog dialog = new CellBroadcastAlertDialog(this,
    277                 cbm.getDialogTitleResource(), cbm.getMessageBody(),
    278                 isEmergencyAlert, cbm.getDeliveryTime());
    279         dialog.show();
    280     }
    281 }
    282