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.bluetooth.BluetoothAdapter;
     38 import android.bluetooth.BluetoothDevice;
     39 import android.content.DialogInterface;
     40 import android.content.Intent;
     41 import android.net.Uri;
     42 import android.os.Bundle;
     43 import android.os.Handler;
     44 import android.util.Log;
     45 import android.view.View;
     46 import android.widget.TextView;
     47 import android.widget.Toast;
     48 import android.database.ContentObserver;
     49 import android.widget.ProgressBar;
     50 
     51 import com.android.internal.app.AlertActivity;
     52 import com.android.internal.app.AlertController;
     53 import android.app.NotificationManager;
     54 import android.text.format.Formatter;
     55 
     56 /**
     57  * Handle all transfer related dialogs: -Ongoing transfer -Receiving one file
     58  * dialog -Sending one file dialog -sending multiple files dialog -Complete
     59  * transfer -receive -receive success, will trigger corresponding handler
     60  * -receive fail dialog -send -send success dialog -send fail dialog -Other
     61  * dialogs - - DIALOG_RECEIVE_ONGOING will transition to
     62  * DIALOG_RECEIVE_COMPLETE_SUCCESS or DIALOG_RECEIVE_COMPLETE_FAIL
     63  * DIALOG_SEND_ONGOING will transition to DIALOG_SEND_COMPLETE_SUCCESS or
     64  * DIALOG_SEND_COMPLETE_FAIL
     65  */
     66 public class BluetoothOppTransferActivity extends AlertActivity implements
     67         DialogInterface.OnClickListener {
     68     private static final String TAG = "BluetoothOppTransferActivity";
     69     private static final boolean D = Constants.DEBUG;
     70     private static final boolean V = Constants.VERBOSE;
     71 
     72     private Uri mUri;
     73 
     74     // ongoing transfer-0 complete transfer-1
     75     boolean mIsComplete;
     76 
     77     private BluetoothOppTransferInfo mTransInfo;
     78 
     79     private ProgressBar mProgressTransfer;
     80 
     81     private TextView mPercentView;
     82 
     83     private AlertController.AlertParams mPara;
     84 
     85     private View mView = null;
     86 
     87     private TextView mLine1View, mLine2View, mLine3View, mLine5View;
     88 
     89     private int mWhichDialog;
     90 
     91     private BluetoothAdapter mAdapter;
     92 
     93     // Dialogs definition:
     94     // Receive progress dialog
     95     public static final int DIALOG_RECEIVE_ONGOING = 0;
     96 
     97     // Receive complete and success dialog
     98     public static final int DIALOG_RECEIVE_COMPLETE_SUCCESS = 1;
     99 
    100     // Receive complete and fail dialog: will display some fail reason
    101     public static final int DIALOG_RECEIVE_COMPLETE_FAIL = 2;
    102 
    103     // Send progress dialog
    104     public static final int DIALOG_SEND_ONGOING = 3;
    105 
    106     // Send complete and success dialog
    107     public static final int DIALOG_SEND_COMPLETE_SUCCESS = 4;
    108 
    109     // Send complete and fail dialog: will let user retry
    110     public static final int DIALOG_SEND_COMPLETE_FAIL = 5;
    111 
    112     /** Observer to get notified when the content observer's data changes */
    113     private BluetoothTransferContentObserver mObserver;
    114 
    115     // do not update button during activity creating, only update when db
    116     // changes after activity created
    117     private boolean mNeedUpdateButton = false;
    118 
    119     private class BluetoothTransferContentObserver extends ContentObserver {
    120         public BluetoothTransferContentObserver() {
    121             super(new Handler());
    122         }
    123 
    124         @Override
    125         public void onChange(boolean selfChange) {
    126             if (V) Log.v(TAG, "received db changes.");
    127             mNeedUpdateButton = true;
    128             updateProgressbar();
    129         }
    130     }
    131 
    132     @Override
    133     protected void onCreate(Bundle savedInstanceState) {
    134         super.onCreate(savedInstanceState);
    135         Intent intent = getIntent();
    136         mUri = intent.getData();
    137 
    138         mTransInfo = new BluetoothOppTransferInfo();
    139         mTransInfo = BluetoothOppUtility.queryRecord(this, mUri);
    140         if (mTransInfo == null) {
    141             if (V) Log.e(TAG, "Error: Can not get data from db");
    142             finish();
    143             return;
    144         }
    145 
    146         mIsComplete = BluetoothShare.isStatusCompleted(mTransInfo.mStatus);
    147 
    148         displayWhichDialog();
    149 
    150         // update progress bar for ongoing transfer
    151         if (!mIsComplete) {
    152             mObserver = new BluetoothTransferContentObserver();
    153             getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true,
    154                     mObserver);
    155         }
    156 
    157         if (mWhichDialog != DIALOG_SEND_ONGOING && mWhichDialog != DIALOG_RECEIVE_ONGOING) {
    158             // set this record to INVISIBLE
    159             BluetoothOppUtility.updateVisibilityToHidden(this, mUri);
    160         }
    161 
    162         mAdapter = BluetoothAdapter.getDefaultAdapter();
    163 
    164         // Set up the "dialog"
    165         setUpDialog();
    166     }
    167 
    168     @Override
    169     protected void onDestroy() {
    170         if (D) Log.d(TAG, "onDestroy()");
    171 
    172         if (mObserver != null) {
    173             getContentResolver().unregisterContentObserver(mObserver);
    174         }
    175         super.onDestroy();
    176     }
    177 
    178     private void displayWhichDialog() {
    179         int direction = mTransInfo.mDirection;
    180         boolean isSuccess = BluetoothShare.isStatusSuccess(mTransInfo.mStatus);
    181         boolean isComplete = BluetoothShare.isStatusCompleted(mTransInfo.mStatus);
    182 
    183         if (direction == BluetoothShare.DIRECTION_INBOUND) {
    184             if (isComplete == true) {
    185                 if (isSuccess == true) {
    186                     // should not go here
    187                     mWhichDialog = DIALOG_RECEIVE_COMPLETE_SUCCESS;
    188                 } else if (isSuccess == false) {
    189                     mWhichDialog = DIALOG_RECEIVE_COMPLETE_FAIL;
    190                 }
    191             } else if (isComplete == false) {
    192                 mWhichDialog = DIALOG_RECEIVE_ONGOING;
    193             }
    194         } else if (direction == BluetoothShare.DIRECTION_OUTBOUND) {
    195             if (isComplete == true) {
    196                 if (isSuccess == true) {
    197                     mWhichDialog = DIALOG_SEND_COMPLETE_SUCCESS;
    198 
    199                 } else if (isSuccess == false) {
    200                     mWhichDialog = DIALOG_SEND_COMPLETE_FAIL;
    201                 }
    202             } else if (isComplete == false) {
    203                 mWhichDialog = DIALOG_SEND_ONGOING;
    204             }
    205         }
    206 
    207         if (V) Log.v(TAG, " WhichDialog/dir/isComplete/failOrSuccess" + mWhichDialog + direction
    208                     + isComplete + isSuccess);
    209     }
    210 
    211     private void setUpDialog() {
    212         // final AlertController.AlertParams p = mAlertParams;
    213         mPara = mAlertParams;
    214         mPara.mIconId = android.R.drawable.ic_dialog_info;
    215         mPara.mTitle = getString(R.string.download_title);
    216 
    217         if ((mWhichDialog == DIALOG_RECEIVE_ONGOING) || (mWhichDialog == DIALOG_SEND_ONGOING)) {
    218             mPara.mPositiveButtonText = getString(R.string.download_ok);
    219             mPara.mPositiveButtonListener = this;
    220             mPara.mNegativeButtonText = getString(R.string.download_cancel);
    221             mPara.mNegativeButtonListener = this;
    222         } else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
    223             mPara.mPositiveButtonText = getString(R.string.download_succ_ok);
    224             mPara.mPositiveButtonListener = this;
    225         } else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_FAIL) {
    226             mPara.mIconId = android.R.drawable.ic_dialog_alert;
    227             mPara.mPositiveButtonText = getString(R.string.download_fail_ok);
    228             mPara.mPositiveButtonListener = this;
    229         } else if (mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
    230             mPara.mPositiveButtonText = getString(R.string.upload_succ_ok);
    231             mPara.mPositiveButtonListener = this;
    232         } else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
    233             mPara.mIconId = android.R.drawable.ic_dialog_alert;
    234             mPara.mPositiveButtonText = getString(R.string.upload_fail_ok);
    235             mPara.mPositiveButtonListener = this;
    236             mPara.mNegativeButtonText = getString(R.string.upload_fail_cancel);
    237             mPara.mNegativeButtonListener = this;
    238         }
    239         mPara.mView = createView();
    240         setupAlert();
    241     }
    242 
    243     private View createView() {
    244 
    245         mView = getLayoutInflater().inflate(R.layout.file_transfer, null);
    246 
    247         mProgressTransfer = (ProgressBar)mView.findViewById(R.id.progress_transfer);
    248         mPercentView = (TextView)mView.findViewById(R.id.progress_percent);
    249 
    250         customizeViewContent();
    251 
    252         // no need update button when activity creating
    253         mNeedUpdateButton = false;
    254         updateProgressbar();
    255 
    256         return mView;
    257     }
    258 
    259     /**
    260      * customize the content of view
    261      */
    262     private void customizeViewContent() {
    263         String tmp;
    264 
    265         if (mWhichDialog == DIALOG_RECEIVE_ONGOING
    266                 || mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
    267             mLine1View = (TextView)mView.findViewById(R.id.line1_view);
    268             tmp = getString(R.string.download_line1, mTransInfo.mDeviceName);
    269             mLine1View.setText(tmp);
    270             mLine2View = (TextView)mView.findViewById(R.id.line2_view);
    271             tmp = getString(R.string.download_line2, mTransInfo.mFileName);
    272             mLine2View.setText(tmp);
    273             mLine3View = (TextView)mView.findViewById(R.id.line3_view);
    274             tmp = getString(R.string.download_line3, Formatter.formatFileSize(this,
    275                     mTransInfo.mTotalBytes));
    276             mLine3View.setText(tmp);
    277             mLine5View = (TextView)mView.findViewById(R.id.line5_view);
    278             if (mWhichDialog == DIALOG_RECEIVE_ONGOING) {
    279                 tmp = getString(R.string.download_line5);
    280             } else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
    281                 tmp = getString(R.string.download_succ_line5);
    282             }
    283             mLine5View.setText(tmp);
    284         } else if (mWhichDialog == DIALOG_SEND_ONGOING
    285                 || mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
    286             mLine1View = (TextView)mView.findViewById(R.id.line1_view);
    287             tmp = getString(R.string.upload_line1, mTransInfo.mDeviceName);
    288             mLine1View.setText(tmp);
    289             mLine2View = (TextView)mView.findViewById(R.id.line2_view);
    290             tmp = getString(R.string.download_line2, mTransInfo.mFileName);
    291             mLine2View.setText(tmp);
    292             mLine3View = (TextView)mView.findViewById(R.id.line3_view);
    293             tmp = getString(R.string.upload_line3, mTransInfo.mFileType, Formatter.formatFileSize(
    294                     this, mTransInfo.mTotalBytes));
    295             mLine3View.setText(tmp);
    296             mLine5View = (TextView)mView.findViewById(R.id.line5_view);
    297             if (mWhichDialog == DIALOG_SEND_ONGOING) {
    298                 tmp = getString(R.string.upload_line5);
    299             } else if (mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
    300                 tmp = getString(R.string.upload_succ_line5);
    301             }
    302             mLine5View.setText(tmp);
    303         } else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_FAIL) {
    304             if (mTransInfo.mStatus == BluetoothShare.STATUS_ERROR_SDCARD_FULL) {
    305                 mLine1View = (TextView)mView.findViewById(R.id.line1_view);
    306                 tmp = getString(R.string.bt_sm_2_1, mTransInfo.mDeviceName);
    307                 mLine1View.setText(tmp);
    308                 mLine2View = (TextView)mView.findViewById(R.id.line2_view);
    309                 tmp = getString(R.string.download_fail_line2, mTransInfo.mFileName);
    310                 mLine2View.setText(tmp);
    311                 mLine3View = (TextView)mView.findViewById(R.id.line3_view);
    312                 tmp = getString(R.string.bt_sm_2_2, Formatter.formatFileSize(this,
    313                         mTransInfo.mTotalBytes));
    314                 mLine3View.setText(tmp);
    315             } else {
    316                 mLine1View = (TextView)mView.findViewById(R.id.line1_view);
    317                 tmp = getString(R.string.download_fail_line1);
    318                 mLine1View.setText(tmp);
    319                 mLine2View = (TextView)mView.findViewById(R.id.line2_view);
    320                 tmp = getString(R.string.download_fail_line2, mTransInfo.mFileName);
    321                 mLine2View.setText(tmp);
    322                 mLine3View = (TextView)mView.findViewById(R.id.line3_view);
    323                 tmp = getString(R.string.download_fail_line3, BluetoothOppUtility
    324                         .getStatusDescription(this, mTransInfo.mStatus, mTransInfo.mDeviceName));
    325                 mLine3View.setText(tmp);
    326             }
    327             mLine5View = (TextView)mView.findViewById(R.id.line5_view);
    328             mLine5View.setVisibility(View.GONE);
    329         } else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
    330             mLine1View = (TextView)mView.findViewById(R.id.line1_view);
    331             tmp = getString(R.string.upload_fail_line1, mTransInfo.mDeviceName);
    332             mLine1View.setText(tmp);
    333             mLine2View = (TextView)mView.findViewById(R.id.line2_view);
    334             tmp = getString(R.string.upload_fail_line1_2, mTransInfo.mFileName);
    335             mLine2View.setText(tmp);
    336             mLine3View = (TextView)mView.findViewById(R.id.line3_view);
    337             tmp = getString(R.string.download_fail_line3, BluetoothOppUtility.getStatusDescription(
    338                     this, mTransInfo.mStatus, mTransInfo.mDeviceName));
    339             mLine3View.setText(tmp);
    340             mLine5View = (TextView)mView.findViewById(R.id.line5_view);
    341             mLine5View.setVisibility(View.GONE);
    342         }
    343 
    344         if (BluetoothShare.isStatusError(mTransInfo.mStatus)) {
    345             mProgressTransfer.setVisibility(View.GONE);
    346             mPercentView.setVisibility(View.GONE);
    347         }
    348     }
    349 
    350     public void onClick(DialogInterface dialog, int which) {
    351         switch (which) {
    352             case DialogInterface.BUTTON_POSITIVE:
    353                 if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
    354                     // "Open" - open receive file
    355                     BluetoothOppUtility.openReceivedFile(this, mTransInfo.mFileName,
    356                             mTransInfo.mFileType, mTransInfo.mTimeStamp, mUri);
    357 
    358                     // make current transfer "hidden"
    359                     BluetoothOppUtility.updateVisibilityToHidden(this, mUri);
    360 
    361                     // clear correspondent notification item
    362                     ((NotificationManager)getSystemService(NOTIFICATION_SERVICE))
    363                             .cancel(mTransInfo.mID);
    364                 } else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
    365                     // "try again"
    366 
    367                     // make current transfer "hidden"
    368                     BluetoothOppUtility.updateVisibilityToHidden(this, mUri);
    369 
    370                     // clear correspondent notification item
    371                     ((NotificationManager)getSystemService(NOTIFICATION_SERVICE))
    372                             .cancel(mTransInfo.mID);
    373 
    374                     // retry the failed transfer
    375                     BluetoothOppUtility.retryTransfer(this, mTransInfo);
    376 
    377                     BluetoothDevice remoteDevice = mAdapter.getRemoteDevice(mTransInfo.mDestAddr);
    378 
    379                     // Display toast message
    380                     Toast.makeText(
    381                             this,
    382                             this.getString(R.string.bt_toast_4, BluetoothOppManager.getInstance(
    383                                     this).getDeviceName(remoteDevice)), Toast.LENGTH_SHORT)
    384                             .show();
    385 
    386                 } else if (mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
    387                     BluetoothOppUtility.updateVisibilityToHidden(this, mUri);
    388                     ((NotificationManager)getSystemService(NOTIFICATION_SERVICE))
    389                             .cancel(mTransInfo.mID);
    390                 }
    391                 break;
    392 
    393             case DialogInterface.BUTTON_NEGATIVE:
    394                 if (mWhichDialog == DIALOG_RECEIVE_ONGOING || mWhichDialog == DIALOG_SEND_ONGOING) {
    395                     // "Stop" button
    396                     this.getContentResolver().delete(mUri, null, null);
    397 
    398                     String msg = "";
    399                     if (mWhichDialog == DIALOG_RECEIVE_ONGOING) {
    400                         msg = getString(R.string.bt_toast_3, mTransInfo.mDeviceName);
    401                     } else if (mWhichDialog == DIALOG_SEND_ONGOING) {
    402                         msg = getString(R.string.bt_toast_6, mTransInfo.mDeviceName);
    403                     }
    404                     Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    405 
    406                     ((NotificationManager)getSystemService(NOTIFICATION_SERVICE))
    407                             .cancel(mTransInfo.mID);
    408                 } else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
    409 
    410                     BluetoothOppUtility.updateVisibilityToHidden(this, mUri);
    411                 }
    412                 break;
    413         }
    414         finish();
    415     }
    416 
    417     /**
    418      * Update progress bar per data got from content provider
    419      */
    420     private void updateProgressbar() {
    421         mTransInfo = BluetoothOppUtility.queryRecord(this, mUri);
    422         if (mTransInfo == null) {
    423             if (V) Log.e(TAG, "Error: Can not get data from db");
    424             return;
    425         }
    426 
    427         if (mTransInfo.mTotalBytes == 0) {
    428             // if Max and progress both equal 0, the progress display 100%.
    429             // Below is to fix it.
    430             mProgressTransfer.setMax(100);
    431         } else {
    432             mProgressTransfer.setMax(mTransInfo.mTotalBytes);
    433         }
    434 
    435         mProgressTransfer.setProgress(mTransInfo.mCurrentBytes);
    436 
    437         mPercentView.setText(BluetoothOppUtility.formatProgressText(mTransInfo.mTotalBytes,
    438                 mTransInfo.mCurrentBytes));
    439 
    440         // Handle the case when DIALOG_RECEIVE_ONGOING evolve to
    441         // DIALOG_RECEIVE_COMPLETE_SUCCESS/DIALOG_RECEIVE_COMPLETE_FAIL
    442         // Handle the case when DIALOG_SEND_ONGOING evolve to
    443         // DIALOG_SEND_COMPLETE_SUCCESS/DIALOG_SEND_COMPLETE_FAIL
    444         if (!mIsComplete && BluetoothShare.isStatusCompleted(mTransInfo.mStatus)
    445                 && mNeedUpdateButton) {
    446             displayWhichDialog();
    447             updateButton();
    448             customizeViewContent();
    449         }
    450     }
    451 
    452     /**
    453      * Update button when one transfer goto complete from ongoing
    454      */
    455     private void updateButton() {
    456         if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
    457             mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
    458             mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setText(
    459                     getString(R.string.download_succ_ok));
    460         } else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_FAIL) {
    461             mAlert.setIcon(android.R.drawable.ic_dialog_alert);
    462             mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
    463             mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setText(
    464                     getString(R.string.download_fail_ok));
    465         } else if (mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
    466             mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
    467             mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setText(
    468                     getString(R.string.upload_succ_ok));
    469         } else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
    470             mAlert.setIcon(android.R.drawable.ic_dialog_alert);
    471             mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setText(
    472                     getString(R.string.upload_fail_ok));
    473             mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setText(
    474                     getString(R.string.upload_fail_cancel));
    475         }
    476     }
    477 }
    478