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