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