• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2008-2009, Motorola, Inc.
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * - Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * - Neither the name of the Motorola, Inc. nor the names of its contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.android.bluetooth.opp;
34 
35 import com.android.bluetooth.R;
36 
37 import android.app.Activity;
38 import android.app.AlertDialog;
39 import android.bluetooth.BluetoothAdapter;
40 import android.content.DialogInterface;
41 import android.content.Intent;
42 import android.content.ContentResolver;
43 import android.database.Cursor;
44 import android.net.Uri;
45 import android.os.Bundle;
46 import android.util.Log;
47 import android.view.ContextMenu;
48 import android.view.ContextMenu.ContextMenuInfo;
49 import android.view.Menu;
50 import android.view.MenuInflater;
51 import android.view.MenuItem;
52 import android.view.View;
53 import android.widget.AdapterView;
54 import android.widget.AdapterView.OnItemClickListener;
55 import android.widget.ListView;
56 
57 /**
58  * View showing the user's finished bluetooth opp transfers that the user does
59  * not confirm. Including outbound and inbound transfers, both successful and
60  * failed. *
61  */
62 public class BluetoothOppTransferHistory extends Activity implements
63         View.OnCreateContextMenuListener, OnItemClickListener {
64     private static final String TAG = "BluetoothOppTransferHistory";
65 
66     private static final boolean V = Constants.VERBOSE;
67 
68     private ListView mListView;
69 
70     private Cursor mTransferCursor;
71 
72     private BluetoothOppTransferAdapter mTransferAdapter;
73 
74     private int mIdColumnId;
75 
76     private int mContextMenuPosition;
77 
78     private boolean mShowAllIncoming;
79 
80     private boolean mContextMenu = false;
81 
82     /** Class to handle Notification Manager updates */
83     private BluetoothOppNotification mNotifier;
84 
85     @Override
onCreate(Bundle icicle)86     public void onCreate(Bundle icicle) {
87         super.onCreate(icicle);
88         setContentView(R.layout.bluetooth_transfers_page);
89         mListView = (ListView)findViewById(R.id.list);
90         mListView.setEmptyView(findViewById(R.id.empty));
91 
92         mShowAllIncoming = getIntent().getBooleanExtra(
93                 Constants.EXTRA_SHOW_ALL_FILES, false);
94 
95         String direction;
96         int dir = getIntent().getIntExtra("direction", 0);
97         if (dir == BluetoothShare.DIRECTION_OUTBOUND) {
98             setTitle(getText(R.string.outbound_history_title));
99             direction = "(" + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_OUTBOUND
100                     + ")";
101         } else {
102             if (mShowAllIncoming) {
103                 setTitle(getText(R.string.btopp_live_folder));
104             } else {
105                 setTitle(getText(R.string.inbound_history_title));
106             }
107             direction = "(" + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_INBOUND
108                     + ")";
109         }
110 
111         String selection = BluetoothShare.STATUS + " >= '200' AND " + direction;
112 
113         if (!mShowAllIncoming) {
114             selection = selection + " AND ("
115                     + BluetoothShare.VISIBILITY + " IS NULL OR "
116                     + BluetoothShare.VISIBILITY + " == '"
117                     + BluetoothShare.VISIBILITY_VISIBLE + "')";
118         }
119 
120         final String sortOrder = BluetoothShare.TIMESTAMP + " DESC";
121 
122         mTransferCursor = getContentResolver().query(BluetoothShare.CONTENT_URI,
123                 new String[] {"_id", BluetoothShare.FILENAME_HINT, BluetoothShare.STATUS,
124                         BluetoothShare.TOTAL_BYTES, BluetoothShare._DATA, BluetoothShare.TIMESTAMP,
125                         BluetoothShare.VISIBILITY, BluetoothShare.DESTINATION,
126                         BluetoothShare.DIRECTION},
127                 selection, null, sortOrder);
128 
129         // only attach everything to the listbox if we can access
130         // the transfer database. Otherwise, just show it empty
131         if (mTransferCursor != null) {
132             mIdColumnId = mTransferCursor.getColumnIndexOrThrow(BluetoothShare._ID);
133             // Create a list "controller" for the data
134             mTransferAdapter = new BluetoothOppTransferAdapter(this,
135                     R.layout.bluetooth_transfer_item, mTransferCursor);
136             mListView.setAdapter(mTransferAdapter);
137             mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
138             mListView.setOnCreateContextMenuListener(this);
139             mListView.setOnItemClickListener(this);
140         }
141 
142         mNotifier = new BluetoothOppNotification(this);
143         mContextMenu = false;
144     }
145 
146     @Override
onCreateOptionsMenu(Menu menu)147     public boolean onCreateOptionsMenu(Menu menu) {
148         if (mTransferCursor != null && !mShowAllIncoming) {
149             MenuInflater inflater = getMenuInflater();
150             inflater.inflate(R.menu.transferhistory, menu);
151         }
152         return true;
153     }
154 
155     @Override
onPrepareOptionsMenu(Menu menu)156     public boolean onPrepareOptionsMenu(Menu menu) {
157         if (!mShowAllIncoming) {
158             boolean showClear = getClearableCount() > 0;
159             menu.findItem(R.id.transfer_menu_clear_all).setEnabled(showClear);
160         }
161         return super.onPrepareOptionsMenu(menu);
162     }
163 
164     @Override
onOptionsItemSelected(MenuItem item)165     public boolean onOptionsItemSelected(MenuItem item) {
166         switch (item.getItemId()) {
167             case R.id.transfer_menu_clear_all:
168                 promptClearList();
169                 return true;
170         }
171         return false;
172     }
173 
174     @Override
onContextItemSelected(MenuItem item)175     public boolean onContextItemSelected(MenuItem item) {
176         if (mTransferCursor.getCount() == 0) {
177             Log.i(TAG, "History is already cleared, not clearing again");
178             return true;
179         }
180         mTransferCursor.moveToPosition(mContextMenuPosition);
181         switch (item.getItemId()) {
182             case R.id.transfer_menu_open:
183                 openCompleteTransfer();
184                 updateNotificationWhenBtDisabled();
185                 return true;
186 
187             case R.id.transfer_menu_clear:
188                 int sessionId = mTransferCursor.getInt(mIdColumnId);
189                 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + sessionId);
190                 BluetoothOppUtility.updateVisibilityToHidden(this, contentUri);
191                 updateNotificationWhenBtDisabled();
192                 return true;
193         }
194         return false;
195     }
196 
197     @Override
onDestroy()198     protected void onDestroy() {
199         if (mTransferCursor != null) {
200             mTransferCursor.close();
201         }
202         super.onDestroy();
203     }
204 
205     @Override
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)206     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
207         if (mTransferCursor != null) {
208             mContextMenu = true;
209             AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
210             mTransferCursor.moveToPosition(info.position);
211             mContextMenuPosition = info.position;
212 
213             String fileName = mTransferCursor.getString(mTransferCursor
214                     .getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT));
215             if (fileName == null) {
216                 fileName = this.getString(R.string.unknown_file);
217             }
218             menu.setHeaderTitle(fileName);
219 
220             MenuInflater inflater = getMenuInflater();
221             if (mShowAllIncoming) {
222                 inflater.inflate(R.menu.receivedfilescontextfinished, menu);
223             } else {
224                 inflater.inflate(R.menu.transferhistorycontextfinished, menu);
225             }
226         }
227     }
228 
229     /**
230      * Prompt the user if they would like to clear the transfer history
231      */
promptClearList()232     private void promptClearList() {
233         new AlertDialog.Builder(this).setTitle(R.string.transfer_clear_dlg_title).setMessage(
234                 R.string.transfer_clear_dlg_msg).setPositiveButton(android.R.string.ok,
235                 new DialogInterface.OnClickListener() {
236                     public void onClick(DialogInterface dialog, int whichButton) {
237                         clearAllDownloads();
238                     }
239                 }).setNegativeButton(android.R.string.cancel, null).show();
240     }
241 
242     /**
243      * Get the number of finished transfers, including error and success.
244      */
getClearableCount()245     private int getClearableCount() {
246         int count = 0;
247         if (mTransferCursor.moveToFirst()) {
248             while (!mTransferCursor.isAfterLast()) {
249                 int statusColumnId = mTransferCursor.getColumnIndexOrThrow(BluetoothShare.STATUS);
250                 int status = mTransferCursor.getInt(statusColumnId);
251                 if (BluetoothShare.isStatusCompleted(status)) {
252                     count++;
253                 }
254                 mTransferCursor.moveToNext();
255             }
256         }
257         return count;
258     }
259 
260     /**
261      * Clear all finished transfers, error and success transfer items.
262      */
clearAllDownloads()263     private void clearAllDownloads() {
264         if (mTransferCursor.moveToFirst()) {
265             while (!mTransferCursor.isAfterLast()) {
266                 int sessionId = mTransferCursor.getInt(mIdColumnId);
267                 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + sessionId);
268                 BluetoothOppUtility.updateVisibilityToHidden(this, contentUri);
269 
270                 mTransferCursor.moveToNext();
271             }
272             updateNotificationWhenBtDisabled();
273         }
274     }
275 
276     /*
277      * (non-Javadoc)
278      * @see
279      * android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget
280      * .AdapterView, android.view.View, int, long)
281      */
onItemClick(AdapterView<?> parent, View view, int position, long id)282     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
283         // Open the selected item
284         if (V) Log.v(TAG, "onItemClick: ContextMenu = " + mContextMenu);
285         if (!mContextMenu) {
286             mTransferCursor.moveToPosition(position);
287             openCompleteTransfer();
288             updateNotificationWhenBtDisabled();
289         }
290         mContextMenu = false;
291     }
292 
293     /**
294      * Open the selected finished transfer. mDownloadCursor must be moved to
295      * appropriate position before calling this function
296      */
openCompleteTransfer()297     private void openCompleteTransfer() {
298         int sessionId = mTransferCursor.getInt(mIdColumnId);
299         Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + sessionId);
300         BluetoothOppTransferInfo transInfo = BluetoothOppUtility.queryRecord(this, contentUri);
301         if (transInfo == null) {
302             Log.e(TAG, "Error: Can not get data from db");
303             return;
304         }
305         if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND
306                 && BluetoothShare.isStatusSuccess(transInfo.mStatus)) {
307             // if received file successfully, open this file
308             BluetoothOppUtility.updateVisibilityToHidden(this, contentUri);
309             BluetoothOppUtility.openReceivedFile(this, transInfo.mFileName, transInfo.mFileType,
310                     transInfo.mTimeStamp, contentUri);
311         } else {
312             Intent in = new Intent(this, BluetoothOppTransferActivity.class);
313             in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
314             in.setDataAndNormalize(contentUri);
315             this.startActivity(in);
316         }
317     }
318 
319     /**
320      * When Bluetooth is disabled, notification can not be updated by
321      * ContentObserver in OppService, so need update manually.
322      */
updateNotificationWhenBtDisabled()323     private void updateNotificationWhenBtDisabled() {
324         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
325         if (!adapter.isEnabled()) {
326             if (V) Log.v(TAG, "Bluetooth is not enabled, update notification manually.");
327             mNotifier.updateNotification();
328         }
329     }
330 }
331