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