• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onCreate(Bundle savedInstanceState)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
onDestroy()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. */
databaseContentChanged()99     void databaseContentChanged() {
100         runOnUiThread(new Runnable() {
101             public void run() {
102                 mAdapterCursor.requery();
103             }
104         });
105     }
106 
107     @Override
onNewIntent(Intent intent)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
onPrepareOptionsMenu(Menu menu)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
onOptionsItemSelected(MenuItem item)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
onListItemClick(ListView l, View v, int position, long id)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
onContextItemSelected(MenuItem item)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 
showDialogAndMarkRead(Cursor cursor)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      */
confirmDeleteThread(long rowId)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      */
confirmDeleteThreadDialog(DeleteThreadListener listener, boolean deleteAll, Context context)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 
DeleteThreadListener(long rowId)233         public DeleteThreadListener(long rowId) {
234             mRowId = rowId;
235         }
236 
onClick(DialogInterface dialog, int whichButton)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 
parseIntent(Intent intent)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