Home | History | Annotate | Download | only in opp
      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.database.Cursor;
     43 import android.net.Uri;
     44 import android.os.Bundle;
     45 import android.util.Log;
     46 import android.view.ContextMenu;
     47 import android.view.Menu;
     48 import android.view.MenuInflater;
     49 import android.view.MenuItem;
     50 import android.view.View;
     51 import android.view.ContextMenu.ContextMenuInfo;
     52 import android.widget.AdapterView;
     53 import android.widget.ListView;
     54 import android.widget.AdapterView.OnItemClickListener;
     55 
     56 /**
     57  * View showing the user's finished bluetooth opp transfers that the user does
     58  * not confirm. Including outbound and inbound transfers, both successful and
     59  * failed. *
     60  */
     61 public class BluetoothOppTransferHistory extends Activity implements
     62         View.OnCreateContextMenuListener, OnItemClickListener {
     63     private static final String TAG = "BluetoothOppTransferHistory";
     64 
     65     private static final boolean V = Constants.VERBOSE;
     66 
     67     private ListView mListView;
     68 
     69     private Cursor mTransferCursor;
     70 
     71     private BluetoothOppTransferAdapter mTransferAdapter;
     72 
     73     private int mIdColumnId;
     74 
     75     private int mContextMenuPosition;
     76 
     77     private boolean mShowAllIncoming;
     78 
     79     private boolean mContextMenu = false;
     80 
     81     /** Class to handle Notification Manager updates */
     82     private BluetoothOppNotification mNotifier;
     83 
     84     @Override
     85     public void onCreate(Bundle icicle) {
     86         super.onCreate(icicle);
     87         setContentView(R.layout.bluetooth_transfers_page);
     88         mListView = (ListView)findViewById(R.id.list);
     89         mListView.setEmptyView(findViewById(R.id.empty));
     90 
     91         mShowAllIncoming = getIntent().getBooleanExtra(
     92                 Constants.EXTRA_SHOW_ALL_FILES, false);
     93 
     94         String direction;
     95         int dir = getIntent().getIntExtra("direction", 0);
     96         if (dir == BluetoothShare.DIRECTION_OUTBOUND) {
     97             setTitle(getText(R.string.outbound_history_title));
     98             direction = "(" + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_OUTBOUND
     99                     + ")";
    100         } else {
    101             if (mShowAllIncoming) {
    102                 setTitle(getText(R.string.btopp_live_folder));
    103             } else {
    104                 setTitle(getText(R.string.inbound_history_title));
    105             }
    106             direction = "(" + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_INBOUND
    107                     + ")";
    108         }
    109 
    110         String selection = BluetoothShare.STATUS + " >= '200' AND " + direction;
    111 
    112         if (!mShowAllIncoming) {
    113             selection = selection + " AND ("
    114                     + BluetoothShare.VISIBILITY + " IS NULL OR "
    115                     + BluetoothShare.VISIBILITY + " == '"
    116                     + BluetoothShare.VISIBILITY_VISIBLE + "')";
    117         }
    118 
    119         final String sortOrder = BluetoothShare.TIMESTAMP + " DESC";
    120 
    121         mTransferCursor = managedQuery(BluetoothShare.CONTENT_URI, new String[] {
    122                 "_id", BluetoothShare.FILENAME_HINT, BluetoothShare.STATUS,
    123                 BluetoothShare.TOTAL_BYTES, BluetoothShare._DATA, BluetoothShare.TIMESTAMP,
    124                 BluetoothShare.VISIBILITY, BluetoothShare.DESTINATION, BluetoothShare.DIRECTION
    125         }, selection, sortOrder);
    126 
    127         // only attach everything to the listbox if we can access
    128         // the transfer database. Otherwise, just show it empty
    129         if (mTransferCursor != null) {
    130             mIdColumnId = mTransferCursor.getColumnIndexOrThrow(BluetoothShare._ID);
    131             // Create a list "controller" for the data
    132             mTransferAdapter = new BluetoothOppTransferAdapter(this,
    133                     R.layout.bluetooth_transfer_item, mTransferCursor);
    134             mListView.setAdapter(mTransferAdapter);
    135             mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
    136             mListView.setOnCreateContextMenuListener(this);
    137             mListView.setOnItemClickListener(this);
    138         }
    139 
    140         mNotifier = new BluetoothOppNotification(this);
    141         mContextMenu = false;
    142     }
    143 
    144     @Override
    145     public boolean onCreateOptionsMenu(Menu menu) {
    146         if (mTransferCursor != null && !mShowAllIncoming) {
    147             MenuInflater inflater = getMenuInflater();
    148             inflater.inflate(R.menu.transferhistory, menu);
    149         }
    150         return true;
    151     }
    152 
    153     @Override
    154     public boolean onPrepareOptionsMenu(Menu menu) {
    155         if (!mShowAllIncoming) {
    156             boolean showClear = getClearableCount() > 0;
    157             menu.findItem(R.id.transfer_menu_clear_all).setEnabled(showClear);
    158         }
    159         return super.onPrepareOptionsMenu(menu);
    160     }
    161 
    162     @Override
    163     public boolean onOptionsItemSelected(MenuItem item) {
    164         switch (item.getItemId()) {
    165             case R.id.transfer_menu_clear_all:
    166                 promptClearList();
    167                 return true;
    168         }
    169         return false;
    170     }
    171 
    172     @Override
    173     public boolean onContextItemSelected(MenuItem item) {
    174         mTransferCursor.moveToPosition(mContextMenuPosition);
    175         switch (item.getItemId()) {
    176             case R.id.transfer_menu_open:
    177                 openCompleteTransfer();
    178                 updateNotificationWhenBtDisabled();
    179                 return true;
    180 
    181             case R.id.transfer_menu_clear:
    182                 int sessionId = mTransferCursor.getInt(mIdColumnId);
    183                 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + sessionId);
    184                 BluetoothOppUtility.updateVisibilityToHidden(this, contentUri);
    185                 updateNotificationWhenBtDisabled();
    186                 return true;
    187         }
    188         return false;
    189     }
    190 
    191     @Override
    192     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    193         if (mTransferCursor != null) {
    194             mContextMenu = true;
    195             AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
    196             mTransferCursor.moveToPosition(info.position);
    197             mContextMenuPosition = info.position;
    198 
    199             String fileName = mTransferCursor.getString(mTransferCursor
    200                     .getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT));
    201             if (fileName == null) {
    202                 fileName = this.getString(R.string.unknown_file);
    203             }
    204             menu.setHeaderTitle(fileName);
    205 
    206             MenuInflater inflater = getMenuInflater();
    207             if (mShowAllIncoming) {
    208                 inflater.inflate(R.menu.receivedfilescontextfinished, menu);
    209             } else {
    210                 inflater.inflate(R.menu.transferhistorycontextfinished, menu);
    211             }
    212         }
    213     }
    214 
    215     /**
    216      * Prompt the user if they would like to clear the transfer history
    217      */
    218     private void promptClearList() {
    219         new AlertDialog.Builder(this).setTitle(R.string.transfer_clear_dlg_title).setMessage(
    220                 R.string.transfer_clear_dlg_msg).setPositiveButton(android.R.string.ok,
    221                 new DialogInterface.OnClickListener() {
    222                     public void onClick(DialogInterface dialog, int whichButton) {
    223                         clearAllDownloads();
    224                     }
    225                 }).setNegativeButton(android.R.string.cancel, null).show();
    226     }
    227 
    228     /**
    229      * Get the number of finished transfers, including error and success.
    230      */
    231     private int getClearableCount() {
    232         int count = 0;
    233         if (mTransferCursor.moveToFirst()) {
    234             while (!mTransferCursor.isAfterLast()) {
    235                 int statusColumnId = mTransferCursor.getColumnIndexOrThrow(BluetoothShare.STATUS);
    236                 int status = mTransferCursor.getInt(statusColumnId);
    237                 if (BluetoothShare.isStatusCompleted(status)) {
    238                     count++;
    239                 }
    240                 mTransferCursor.moveToNext();
    241             }
    242         }
    243         return count;
    244     }
    245 
    246     /**
    247      * Clear all finished transfers, error and success transfer items.
    248      */
    249     private void clearAllDownloads() {
    250         if (mTransferCursor.moveToFirst()) {
    251             while (!mTransferCursor.isAfterLast()) {
    252                 int sessionId = mTransferCursor.getInt(mIdColumnId);
    253                 Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + sessionId);
    254                 BluetoothOppUtility.updateVisibilityToHidden(this, contentUri);
    255 
    256                 mTransferCursor.moveToNext();
    257             }
    258             updateNotificationWhenBtDisabled();
    259         }
    260     }
    261 
    262     /*
    263      * (non-Javadoc)
    264      * @see
    265      * android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget
    266      * .AdapterView, android.view.View, int, long)
    267      */
    268     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    269         // Open the selected item
    270         if (V) Log.v(TAG, "onItemClick: ContextMenu = " + mContextMenu);
    271         if (!mContextMenu) {
    272             mTransferCursor.moveToPosition(position);
    273             openCompleteTransfer();
    274             updateNotificationWhenBtDisabled();
    275         }
    276         mContextMenu = false;
    277     }
    278 
    279     /**
    280      * Open the selected finished transfer. mDownloadCursor must be moved to
    281      * appropriate position before calling this function
    282      */
    283     private void openCompleteTransfer() {
    284         int sessionId = mTransferCursor.getInt(mIdColumnId);
    285         Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + sessionId);
    286         BluetoothOppTransferInfo transInfo = BluetoothOppUtility.queryRecord(this, contentUri);
    287         if (transInfo == null) {
    288             Log.e(TAG, "Error: Can not get data from db");
    289             return;
    290         }
    291         if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND
    292                 && BluetoothShare.isStatusSuccess(transInfo.mStatus)) {
    293             // if received file successfully, open this file
    294             BluetoothOppUtility.updateVisibilityToHidden(this, contentUri);
    295             BluetoothOppUtility.openReceivedFile(this, transInfo.mFileName, transInfo.mFileType,
    296                     transInfo.mTimeStamp, contentUri);
    297         } else {
    298             Intent in = new Intent(this, BluetoothOppTransferActivity.class);
    299             in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    300             in.setDataAndNormalize(contentUri);
    301             this.startActivity(in);
    302         }
    303     }
    304 
    305     /**
    306      * When Bluetooth is disabled, notification can not be updated by
    307      * ContentObserver in OppService, so need update manually.
    308      */
    309     private void updateNotificationWhenBtDisabled() {
    310         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    311         if (!adapter.isEnabled()) {
    312             if (V) Log.v(TAG, "Bluetooth is not enabled, update notification manually.");
    313             mNotifier.updateNotification();
    314         }
    315     }
    316 }
    317