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