记一笔自己的sb行为---工作中修改第一个bug
2012-08-15 15:27 ...平..淡... 阅读(438) 评论(0) 编辑 收藏 举报问题1:文件管理器与图库中队同一张图片的删除操作未同步,导致文件管理器以蓝牙分享图片是报错!
描述:
【操作步骤】
1.文件管理器打开某张图片-home返回idle
2.图库中删除文件管理器中的图片->home->文件管理器->仍进入图片预览缓存界面->分享选择蓝牙发送
【实际结果】蓝牙进程意外停止
【预期结果】未知文件(因为实际已删除,只是缓存)不能发送
【log文件】
根据报错的情况在源码中找到insertShare方法:
1 519 private void insertShare(Cursor cursor, int arrayPos) { 2 520 BluetoothOppShareInfo info = new BluetoothOppShareInfo( 3 521 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)), 4 522 cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.URI)), 5 523 cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT)), 6 524 cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare._DATA)), 7 525 cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.MIMETYPE)), 8 526 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)), 9 527 cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.DESTINATION)), 10 528 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)), 11 529 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)), 12 530 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.STATUS)), 13 531 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)), 14 532 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)), 15 533 cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)), 16 534 cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 17 535 18 536 if (V) { 19 537 Log.v(TAG, "Service adding new entry"); 20 538 Log.v(TAG, "ID : " + info.mId); 21 539 // Log.v(TAG, "URI : " + ((info.mUri != null) ? "yes" : "no")); 22 540 Log.v(TAG, "URI : " + info.mUri); 23 541 Log.v(TAG, "HINT : " + info.mHint); 24 542 Log.v(TAG, "FILENAME: " + info.mFilename); 25 543 Log.v(TAG, "MIMETYPE: " + info.mMimetype); 26 544 Log.v(TAG, "DIRECTION: " + info.mDirection); 27 545 Log.v(TAG, "DESTINAT: " + info.mDestination); 28 546 Log.v(TAG, "VISIBILI: " + info.mVisibility); 29 547 Log.v(TAG, "CONFIRM : " + info.mConfirm); 30 548 Log.v(TAG, "STATUS : " + info.mStatus); 31 549 Log.v(TAG, "TOTAL : " + info.mTotalBytes); 32 550 Log.v(TAG, "CURRENT : " + info.mCurrentBytes); 33 551 Log.v(TAG, "TIMESTAMP : " + info.mTimestamp); 34 552 Log.v(TAG, "SCANNED : " + info.mMediaScanned); 35 553 } 36 554 37 555 mShares.add(arrayPos, info); 38 556 39 557 /* Mark the info as failed if it's in invalid status */ 40 558 if (info.isObsolete()) { 41 559 Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_UNKNOWN_ERROR); 42 560 } 43 561 /* 44 562 * Add info into a batch. The logic is 45 563 * 1) Only add valid and readyToStart info 46 564 * 2) If there is no batch, create a batch and insert this transfer into batch, 47 565 * then run the batch 48 566 * 3) If there is existing batch and timestamp match, insert transfer into batch 49 567 * 4) If there is existing batch and timestamp does not match, create a new batch and 50 568 * put in queue 51 569 */ 52 570 53 571 if (info.isReadyToStart()) { 54 572 if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 55 573 /* check if the file exists */ 56 574 try { 57 575 InputStream i = getContentResolver().openInputStream(Uri.parse(info.mUri)); 58 576 //i.close(); 59 577 } catch (FileNotFoundException e) { 60 578 Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId); 61 579 Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST); 62 580 return; 63 581 } catch (IOException ex) { 64 582 Log.e(TAG, "IO error when close file for OUTBOUND info " + info.mId); 65 583 return; 66 584 } 67 585 } 68 586 if (mBatchs.size() == 0) { 69 587 BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 70 588 newBatch.mId = mBatchId; 71 589 mBatchId++; 72 590 mBatchs.add(newBatch); 73 591 if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 74 592 if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId 75 593 + " for OUTBOUND info " + info.mId); 76 594 mTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch); 77 595 } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 78 596 if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId 79 597 + " for INBOUND info " + info.mId); 80 598 mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch, 81 599 mServerSession); 82 600 } 83 601 84 602 if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND && mTransfer != null) { 85 603 if (V) Log.v(TAG, "Service start transfer new Batch " + newBatch.mId 86 604 + " for info " + info.mId); 87 605 mTransfer.start(); 88 606 } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND 89 607 && mServerTransfer != null) { 90 608 if (V) Log.v(TAG, "Service start server transfer new Batch " + newBatch.mId 91 609 + " for info " + info.mId); 92 610 mServerTransfer.start(); 93 611 } 94 612 95 613 } else { 96 614 int i = findBatchWithTimeStamp(info.mTimestamp); 97 615 if (i != -1) { 98 616 if (V) Log.v(TAG, "Service add info " + info.mId + " to existing batch " 99 617 + mBatchs.get(i).mId); 100 618 mBatchs.get(i).addShare(info); 101 619 } else { 102 620 // There is ongoing batch 103 621 BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 104 622 newBatch.mId = mBatchId; 105 623 mBatchId++; 106 624 mBatchs.add(newBatch); 107 625 if (V) Log.v(TAG, "Service add new Batch " + newBatch.mId + " for info " + 108 626 info.mId); 109 627 if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) { 110 628 // only allow concurrent serverTransfer in debug mode 111 629 if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 112 630 if (V) Log.v(TAG, "TCP_DEBUG start server transfer new Batch " + 113 631 newBatch.mId + " for info " + info.mId); 114 632 mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, 115 633 newBatch, mServerSession); 116 634 mServerTransfer.start(); 117 635 } 118 636 } 119 637 } 120 638 } 121 639 } 122 640 }
而问题则产生于下面这个if 语句中,摘录如下:
572 if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 573 /* check if the file exists */ 574 try { 575 InputStream i = getContentResolver().openInputStream(Uri.parse(info.mUri)); //问题出在这句 576 //i.close(); 577 } catch (FileNotFoundException e) { 578 Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId); 579 Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST); 580 return; 581 } catch (IOException ex) { 582 Log.e(TAG, "IO error when close file for OUTBOUND info " + info.mId); 583 return; 584 } 585 }
教训:我天真地以为在catch里面找,结果找了不知道多少天了,后来老大果断说try里,我就惊呆了,我笨死啦笨死啦!!!以后要记住这次严峻的教训了....
cb改正方案(初步未fixed):
在try中对uri进行判断,判断是否存在相应 IContentProvider 对象与其关联。
1 Uri u = Uri.parse(info.mFileUri); 2 if(context.getContentResolver().acquireExistingProvider(u) == null){ 3 Looper.prepare(); 4 Toast.makeText(getApplicationContext(), "Unknown file, cannot be send", Toast.LENGTH_SHORT).show(); 5 Looper.loop(); 6 info.mFileType = null; 7 } 8 else 9 info.mFileType = context.getContentResolver().getType(u);
我以为结果没有报错了~~!!!(当时,我进行的操作只有上面写的操作步骤,没有进行重新打开蓝牙等操作)
但是,后来重新打开蓝牙,发现直接弹出"Unknown file, cannot be send",说明打开蓝牙时,也运行BluetoothOppService类的insertShare方法中的if语句。说明打开蓝牙时,也不存在与其关联的IContentProvider对象。
我查看了源码里BluetoothOppService类中对insertShare方法的调用,发现有传递cursor对象。因此我认为,刚开始打开蓝牙时,获取到的cursor值肯定是null,所以我添加了对cursor对象的判断,结果成功fixed.
fixed Bug 如下所示:
1 Uri u = Uri.parse(info.mFileUri); 2 if(cursor != null && context.getContentResolver().acquireExistingProvider(u) == null){ 3 Looper.prepare(); 4 Toast.makeText(getApplicationContext(), "Unknown file, cannot be send", Toast.LENGTH_SHORT).show(); 5 Looper.loop(); 6 info.mFileType = null; 7 } 8 else 9 info.mFileType = context.getContentResolver().getType(u);
知识点:Android:在Service中使用Toast
在Service中使用Toast,我原本以为和在Activity中一样,可以直接用,但发现没有反应。
解决方法1:通过Handler处理。
1 public class TestService extends Service { 2 private Handler handler; 3 @Override 4 public IBinder onBind(Intent intent){ 5 return null; 6 } 7 8 @Override 9 public void onCreate(){ 10 handler = new Handler(Looper.getMainLooper()); 11 handler.post(new Runnable() { 12 @Override 13 public void run() { 14 Toast.makeText(getApplicationContext(), "Test",Toast.LENGTH_SHORT).show(); 15 } 16 }); 17 } 18 }
解决方法2:通过Looper.prepare()和Looper.loop()处理,如fixed Bug中所示。
关于原理,可以查阅