2012-08-17 59 views
2

我不知道爲什麼,但它與Android我從來沒有得到有用的堆棧跟蹤的新版本似乎。他們似乎沒有足夠的幫助我找到導致崩潰的代碼行。例如:堆棧跟蹤從來沒有追溯應用程序代碼

08-17 09:33:38.449: E/AndroidRuntime(14389): FATAL EXCEPTION: main 
08-17 09:33:38.449: E/AndroidRuntime(14389): java.lang.RuntimeException: Unable to resume activity {com.evidence/com.evidence.activity.EvidenceList}: android.database.StaleDataException: Attempted to access a cursor after it has been closed. 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2567) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2595) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1183) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.os.Handler.dispatchMessage(Handler.java:99) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.os.Looper.loop(Looper.java:137) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.ActivityThread.main(ActivityThread.java:4575) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at java.lang.reflect.Method.invokeNative(Native Method) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at java.lang.reflect.Method.invoke(Method.java:511) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at dalvik.system.NativeStart.main(Native Method) 
08-17 09:33:38.449: E/AndroidRuntime(14389): Caused by: android.database.StaleDataException: Attempted to access a cursor after it has been closed. 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.database.BulkCursorToCursorAdaptor.throwIfCursorIsClosed(BulkCursorToCursorAdaptor.java:75) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.database.BulkCursorToCursorAdaptor.requery(BulkCursorToCursorAdaptor.java:144) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.database.CursorWrapper.requery(CursorWrapper.java:186) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.Activity.performRestart(Activity.java:4505) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.Activity.performResume(Activity.java:4531) 
08-17 09:33:38.449: E/AndroidRuntime(14389): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2557) 
08-17 09:33:38.449: E/AndroidRuntime(14389): ... 10 more 

有沒有辦法讓「10多」沒有顯示?

public class EvidenceList extends StandardMenuActivity implements AdapterView.OnItemClickListener { 

    private ApplicationSettings settings; 
    private Context mContext; 
    private Cursor mCursor; 
    private Uri mData; 

    private ImageButton mActiveButton = null; 
    private static final String TAG = EvidenceList.class.getSimpleName(); 
    protected static final int ACTION_LOGIN = 10; 
    protected static final int ACTION_ENTER_PIN = 11; 
    protected static final int ACTION_BULK_EDIT = 12; 

    private static final int DIALOG_CONFIRM_DELETE = 2; 
    private static final int DIALOG_LOADING = 3; 
    private static final int DIALOG_FILES_MISSING = 4; 

    private static final int MENU_ITEM_CANCEL_UPLOAD = 10001; 
    private static final int MENU_ITEM_DELETE_EVIDENCE = 10002; 
    private static final int MENU_ITEM_VIEW_EDIT_EVIDENCE = 10003; 
    private EvidenceDBHelper evidenceHelper; 
    protected UploadQueueHelper upHelper; 
    private ListView mListView; 
    EvidenceListCursorAdapter mAdapter;  
    private ImageButton mListAllButton, mListAudioButton, mListVideoButton, mListPhotoButton, mListUploadedButton; 
    private Button uploadButton; 
    private View actionButtonBar, tabButtonBar;  
    private TextView mTitleView; 

    private Button mSelectAllButton, mImportButton; 
    private EvidenceManager mEvidenceManager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     Log.d(TAG, "onCreate"); 
     mContext = getApplicationContext(); 
     settings = ApplicationSettings.getInstance(mContext); 

     mEvidenceManager = EvidenceManager.getInstance(mContext); 
     setContentView(R.layout.evidence_list); 

     actionButtonBar = findViewById(R.id.EvidenceSelectedItemsActionButtonBar); 
     tabButtonBar = findViewById(R.id.EvidenceListTabBar); 

     mData = getIntent().getData(); 
     if (mData == null) { 
      mData = LocalEvidence.CONTENT_URI;//default data 
     } 
     upHelper = new UploadQueueHelper(mContext); 
     evidenceHelper = new EvidenceDBHelper(mContext); 

     mListAllButton = (ImageButton) findViewById(R.id.EvidenceListAllTabButton); 
     mListVideoButton = (ImageButton) findViewById(R.id.EvidenceListVideoTabButton); 
     mListAudioButton = (ImageButton) findViewById(R.id.EvidenceListAudioTabButton); 
     mListPhotoButton = (ImageButton) findViewById(R.id.EvidenceListPhotoTabButton); 
     mListUploadedButton = (ImageButton) findViewById(R.id.EvidenceListUploadTabButton); 
     mTitleView = (TextView) findViewById(R.id.EvidenceListTypeTitle); 
     mSelectAllButton = (Button) findViewById(R.id.CheckAll);   
     mImportButton = (Button) findViewById(R.id.ImportEvidence); 
     mImportButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       showDialog(DIALOG_IMPORT_EVIDENCE); 
      } 
     }); 
     mSelectAllButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       EasyTracker.getTracker().trackEvent(TAG, "select_all", "on", 1); 
       Toast.makeText(mContext, getString(R.string.message_select_all), Toast.LENGTH_SHORT).show(); 
       mAdapter.checkAll(); 
      }   
     }); 

     ListHasCheckedItemsListener checkedItemsListener = new ListHasCheckedItemsListener() { 

      @Override 
      public void onListCheckedStatusChange(boolean hasCheckedItems) { 
       showTabsOrButtons(hasCheckedItems); 

      } 
     }; 
     mListView = (ListView) findViewById(android.R.id.list); 
     mListView.setEmptyView(findViewById(android.R.id.empty)); 
     mCursor = getCursor(); 
     mAdapter = new EvidenceListCursorAdapter(this, mCursor, getUriForCursor(), checkedItemsListener); 
     Log.d(TAG, "onCreate, cursor: " + mCursor + " with [email protected] " + getUriForCursor()); 
     uploadButton = (Button) findViewById(R.id.UploadEvidenceButton); 

     mListView.setAdapter(mAdapter); 
     mListView.setOnItemClickListener(this); 
     setActiveButton(); 
     checkIfIntentHasTab(getIntent()); 

     UploadManagerService.startUploader(this, UploaderAction.OP_START, 1, null); 
    } 

    @Override 
    public void onNewIntent(Intent intent) { 
     checkIfIntentHasTab(intent); 
    } 

    private void checkIfIntentHasTab(Intent intent) { 
     String tab = getIntent().getStringExtra("tab"); 
     if (tab != null) { 
      if (tab.equals("uploads_completed")) { 
       changeView(R.id.EvidenceListUploadTabButton); 
      } else if (tab.equals("all_evidence")) { 
       changeView(R.id.EvidenceListAllTabButton); 
      } else if (tab.equals("videos")) { 
       changeView(R.id.EvidenceListVideoTabButton); 
      } else if (tab.equals("photos")) { 
       changeView(R.id.EvidenceListPhotoTabButton); 
      } else if (tab.equals("audio")) { 
       changeView(R.id.EvidenceListAllTabButton); 
      } else { 
       Log.e(TAG, "no match for tab " + tab); 
      } 
     } 
    } 


    public void titlebarLogoClicked(View button) { 
     Log.d(TAG, "Clicked titlebar"); 
     launchMainActivity(); 
    } 

    public void launchMainActivity() { 
     Intent i = new Intent(this, Home.class); 
     i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     startActivity(i); 

    } 
    //should be called after switching the cursor 
    private void setActiveButton() { 
     if (mData.equals(LocalEvidence.CONTENT_URI)){ 
      mActiveButton = mListAllButton; 
     } else if (mData.equals(LocalEvidence.CONTENT_AUDIO_URI)){ 
      mActiveButton = mListAudioButton; 
     } else if (mData.equals(LocalEvidence.CONTENT_VIDEO_URI)) { 
      mActiveButton = mListVideoButton; 
     } else if (mData.equals(LocalEvidence.CONTENT_PHOTO_URI)) { 
      mActiveButton = mListPhotoButton; 
     } else if (mData.equals(LocalEvidence.CONTENT_UPLOADED_URI)) { 
      mActiveButton = mListUploadedButton; 
     } 
     mActiveButton.setSelected(true); 
     setOthersInactive(); 
    } 
    private void setOthersInactive() { 
     if (mActiveButton != mListAllButton) { 
      mListAllButton.setSelected(false); 
     } 
     if (mActiveButton != mListVideoButton) { 
      mListVideoButton.setSelected(false); 
     } 
     if (mActiveButton != mListAudioButton) { 
      mListAudioButton.setSelected(false); 
     } 
     if (mActiveButton != mListPhotoButton) { 
      mListPhotoButton.setSelected(false); 
     } 
     if (mActiveButton != mListUploadedButton) { 
      mListUploadedButton.setSelected(false); 
     } 
    } 

    private void changeCursor() { 
     mAdapter.changeCursor(getCursor()); 
    } 


    private Cursor getCursor() {   
     return managedQuery(mData, null, null, null, null); 
    } 

    private Uri getUriForCursor() { 
     return LocalEvidence.CONTENT_URI; 
    } 

    @Override 
    protected void onDestroy() { 
     Log.d(TAG, "onDestroy"); 
     mAdapter.close(); 
     super.onDestroy(); 
    } 



    @Override 
    protected void onResume() { 
     super.onResume(); 
     Log.d(TAG, "onResume"); 
     if (!FileUtils.isExternalStorageAvailableAndWritable(mContext)) { 
      Util.showAlertMsgNoExternalStorage(this); 
      return; 
     } 
     if (settings.requiresPin() && settings.getLastPinSuccessEntryTime() < System.currentTimeMillis() - (1000 * 60 * 15)) { 
      sendToEnterPin(); 
      return; 
     } 
     //Set<Long> selections = mAdapter.getSelectedCheckboxMediaIds(); 
     //setTabsOrButtons(selections); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     //super.onSaveInstanceState(outState); 
     //outState. 
    } 
    @Override 
    public void onItemClick(AdapterView<?> l, View v, int position, long id) { 
     Log.d(TAG, "onListItemClick, item clicked with id " + id); 
     Intent openEvidenceIntent = getIntentForEvidenceId(id); 
     startActivity(openEvidenceIntent); 
    } 

    private void uncheckAll() { 
     mAdapter.uncheckAll(); 
    } 

    @Override 
    public void onBackPressed() { 
     Log.d(TAG, "onBackPressed"); 

     if (mAdapter.hasSelectedCheckboxes()) { 
      uncheckAll(); 
     } else { 
      Intent i = new Intent(this, Home.class); 
      i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);   
      startActivity(i); 
      finish(); 
      //super.onBackPressed(); 
     } 
    } 

    @Override 
    protected Dialog onCreateDialog(int id) { 
     Log.d(TAG, "onCreateDialog"); 
     switch (id) { 
      case DIALOG_CONFIRM_DELETE: 
       String msg = getString(R.string.alert_delete_imported); 
       return new AlertDialog.Builder(this) 
         .setMessage(msg) 
         .setCancelable(false) 
         .setPositiveButton(getString(R.string.yes_btn), 
           new DialogInterface.OnClickListener() { 
            public void onClick(DialogInterface dialog, int id) { 
             EvidenceList.this.doRemoveEvidence(); 
            } 
           }) 
         .setNegativeButton(R.string.no_btn, new DialogInterface.OnClickListener() { 
          public void onClick(DialogInterface dialog, int id) { 
           dialog.cancel(); 
          } 
         }).create(); 
      case DIALOG_LOADING: 
       ProgressDialog pdialog = new ProgressDialog(this); 
       pdialog.setMessage(getString(R.string.alert_checking_login)); 
       return pdialog; 
      case DIALOG_FILES_MISSING: 
       return new AlertDialog.Builder(this) 
         .setTitle(getString(R.string.alert_files_missing_title)) 
         .setMessage(getString(R.string.alert_files_missing)) 
         .setNeutralButton(getString(R.string.ok_btn), new OnClickListener() { 
          @Override 
          public void onClick(DialogInterface dialog, int arg1id) { 
           dialog.cancel(); 
          } 
         }).create(); 
      default: 
       return super.onCreateDialog(id); 
     } 

    } 

    public void removeEvidence(View v) { 
     Log.d(TAG, "removeEvidence"); 
     //Toast.makeText(mContext, "Going to delete.. ", Toast.LENGTH_LONG).show(); 
     showDialog(DIALOG_CONFIRM_DELETE); 
    } 

    public void bulkEditEvidence(View v) { 
     Log.d(TAG, "bulkEditEvidence"); 
     EasyTracker.getTracker().trackEvent(TAG, "bulk_edit", "", 1); 
     Set<Long> selections = mAdapter.getSelectedCheckboxMediaIds(); 
     Iterator<Long> selectionIter = selections.iterator(); 
     // Pass the array of id's checked to the intent service. 
     // We need to convert from Long[] to long[] 
     long[] ids = new long[selections.size()]; 
     int i = 0; 
     while(selectionIter.hasNext()) {    
      long curr = selectionIter.next(); 
      ids[i++] = curr; 
     } 
     Intent bulkEditIntent = new Intent(this, BulkEditEvidence.class); 
     bulkEditIntent.putExtra(BulkEditEvidence.EXTRA_EVIDENCE_IDS, ids); 
     startActivityForResult(bulkEditIntent, ACTION_BULK_EDIT); 
    } 

    public void doRemoveEvidence() { 
     Log.d(TAG, "doRemoveEvidence"); 
     EasyTracker.getTracker().trackEvent(TAG, "delete", "", 1); 
     Set<Long> selectedIds = mAdapter.getSelectedCheckboxMediaIds(); 
     if (selectedIds == null || selectedIds.size() < 1) { 
      Toast.makeText(mContext, getString(R.string.alert_no_evidence_removed), Toast.LENGTH_LONG).show(); 
      return; 
     } 
     Iterator<Long> selectedIter = selectedIds.iterator(); 
     List<Long> deleted = new ArrayList<Long>(); 
     while(selectedIter.hasNext()) { 
      long selectedId = selectedIter.next(); 
      Log.d(TAG, "going to delete evidence id: " + selectedId); 
      Evidence ev = evidenceHelper.getEvidencefromMediaRecord(selectedId); 

      if (ev != null) { 
       if (ev.getMediaId() > 0) { 
        //has a media id 
        int rowsAffected = evidenceHelper.deleteById(selectedId); 
        upHelper.deleteById(selectedId); 
        if (rowsAffected >0) { 
         deleted.add(selectedId);       
        } 
       } else { 
        if (ev != null) { 
         try { 
          ev.getFile().delete(); 
          int rowsAffected = evidenceHelper.deleteById(selectedId); 
          upHelper.deleteById(selectedId); 
          if (rowsAffected > 0) { 
           deleted.add(selectedId); 
          } 
         } catch(Exception e) { 
          Log.e(TAG, "error trying to delete evidence " + selectedId + " msg: " + e.getMessage(), e); 
         } 
        } 
       } 
      } else { 
       String msg = String.format(getString(R.string.alert_ev_with_id_could_not_delete), "" + selectedId); 
       Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show(); 
      } 
     } 
     if (deleted != null && deleted.size() > 0) { 
      Long[] deletedArr = deleted.toArray(new Long[1]); 
      mAdapter.uncheckIds(deletedArr); 
     } 
     try { 
      dismissDialog(DIALOG_CONFIRM_DELETE); 
     } catch(Exception e) { 
      //who cares 
     } 
    } 
    public void uploadSelected(View v) throws URISyntaxException, IOException {  
     Log.d(TAG, "uploadSelected"); 
     uploadButton.setEnabled(false); 
     showDialog(DIALOG_LOADING); 
     //if the last time the session was checked was more than 15 minutes (-5 seconds) 
     //then check the session again.. 

     if (!settings.canUserAutoLogin()) { 
      dismissDialog(DIALOG_LOADING); 
      sendToLogin(); 
     } else { 
      doUploadSelected(); 
      uploadButton.setEnabled(true); 
     } 

    } 

    private void sendToLogin() { 
     Intent i = new Intent(Action.LOGIN);   
     startActivityForResult(i, ACTION_LOGIN); 
    } 

    private void sendToEnterPin() { 
     startActivityForResult(new Intent(this, EnterPin.class), ACTION_ENTER_PIN); 
    } 

    private void doUploadSelected() { 
     Log.d(TAG, "doUploadSelected"); 

     Set<Long> selections = mAdapter.getSelectedCheckboxMediaIds(); 
     Iterator<Long> selectionIter = selections.iterator(); 
     // Pass the array of id's checked to the intent service. 
     // We need to convert from Long[] to long[] 

     Long[] origArr = selections.toArray(new Long[selections.size()]); 
     Log.d(TAG, "about to pass evidence IDs for upload | on thread " + Thread.currentThread().getId()); 
     List<Long> toUpload = new ArrayList<Long>(); 
     long[] ev_ids = new long[selections.size()]; 
     int i = 0; 
     boolean alertMissing = false; 
     while(selectionIter.hasNext()) { 
      long curr = selectionIter.next(); 
      Evidence ev = evidenceHelper.getEvidencefromMediaRecord(curr); 
      if (FileUtils.isFileAvailableAndReadable(ev.getFile())) { 
       toUpload.add(curr); 
       ev_ids[i] = curr; 
       i++; 
      } else { 
       alertMissing = true; 
      } 
     } 
     try { 
      dismissDialog(DIALOG_LOADING); 
     } catch(Exception e) {} 

     if (alertMissing) { 
      showDialog(DIALOG_FILES_MISSING); 
     } 
     if (ev_ids.length < 1) { 
      return; 
     } 
     EasyTracker.getTracker().trackEvent(TAG, "upload_selected", "" + ev_ids.length + " items" , 1); 
     UploadManagerService.startUploader(this, UploaderAction.OP_QUEUE_UPLOAD, 1, ev_ids); 

     uploadButton.setEnabled(true); 
     mAdapter.markIdsAsDisabled(origArr); 

    } 

    private void onLoginResult(int resultCode, Intent data) { 
     EasyTracker.getTracker().trackEvent(TAG, "login", "on", (resultCode == RESULT_OK) ? 1 : 0); 
     if (resultCode == RESULT_OK) { 

      doUploadSelected();   
     } else { 
      try { 
       dismissDialog(DIALOG_LOADING); 
      } catch (Exception e) {} 
      uploadButton.setEnabled(true); 
      Toast.makeText(mContext, getString(R.string.alert_cannot_upload_without_internet), Toast.LENGTH_LONG).show(); 
     } 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {     
     Log.d(TAG, "onActivityResult"); 

     switch (requestCode) { 
      case ACTION_LOGIN: 
       onLoginResult(resultCode, data); 
       return; 
      case ACTION_ENTER_PIN: 
       if (resultCode != Activity.RESULT_OK) {     
        finish();//throw error message 
       } 
       return; 
      case ACTION_BULK_EDIT: 
       if (resultCode == RESULT_OK) { 
        uncheckAll(); 
       } 
       return; 
      case ACTION_IMPORT_AUDIO: 
      case ACTION_IMPORT_VIDEO: 
      case ACTION_IMPORT_PHOTO: 
       onImportResult(requestCode, resultCode, data); 
       return;     
      default: 
       super.onActivityResult(requestCode, resultCode, data); 
     } 
    } 

    private void onImportResult(int requestCode, int resultCode, Intent intent) { 

     ImportAction action = ImportAction.IMPORT_PHOTO; 
     if (requestCode == ACTION_IMPORT_AUDIO) { 
      action = ImportAction.IMPORT_AUDIO; 
     } else if (requestCode == ACTION_IMPORT_VIDEO) { 
      action = ImportAction.IMPORT_VIDEO; 
     } 
     EasyTracker.getTracker().trackEvent(TAG, "import", action.toString(), resultCode == RESULT_OK ? 1 : 0); 
     if (resultCode == RESULT_OK) { 
      Evidence ev = mEvidenceManager.importEvidence(this, intent, action); 
      if (ev != null) { 
       launchEvidenceListActivity(null); 
       BackupService.start(this, BackupService.OP_DATA_CHANGED); 
      } 
     } 
    } 


    public void showTabsOrButtons(boolean hasCheckedItems) {   
     if (hasCheckedItems) { 
      tabButtonBar.setVisibility(View.INVISIBLE); 
      actionButtonBar.setVisibility(View.VISIBLE); 
      if (mData.equals(LocalEvidence.CONTENT_UPLOADED_URI)) { 
       actionButtonBar.findViewById(R.id.UploadEvidenceButton).setVisibility(View.GONE); 
       actionButtonBar.findViewById(R.id.BulkEditEvidenceButton).setVisibility(View.GONE); 
      } else { 
       actionButtonBar.findViewById(R.id.UploadEvidenceButton).setVisibility(View.VISIBLE); 
      } 
     } else { 
      actionButtonBar.setVisibility(View.GONE); 
      tabButtonBar.setVisibility(View.VISIBLE); 
     } 
    } 

    public void changeView(int id) { 
     Uri newUri = null; 
     String newTitle = ""; 
     if (id == R.id.EvidenceListAllTabButton) { 
      newUri = LocalEvidence.CONTENT_URI; 
      newTitle = getString(R.string.tab_all_pending_upload); 
      EasyTracker.getTracker().trackEvent(TAG, "switched_tab", "all", 1); 
     } else if (id == R.id.EvidenceListAudioTabButton) { 
      newUri = LocalEvidence.CONTENT_AUDIO_URI; 
      newTitle = getString(R.string.tab_audio_pending_upload); 
      EasyTracker.getTracker().trackEvent(TAG, "switched_tab", "audio", 1); 
     } else if (id == R.id.EvidenceListPhotoTabButton) { 
      newUri = LocalEvidence.CONTENT_PHOTO_URI; 
      newTitle = getString(R.string.tab_photos_pending_upload); 
      EasyTracker.getTracker().trackEvent(TAG, "switched_tab", "photos", 1); 
     } else if (id == R.id.EvidenceListVideoTabButton) { 
      newUri = LocalEvidence.CONTENT_VIDEO_URI; 
      newTitle = getString(R.string.tab_video_pending_upload); 
      EasyTracker.getTracker().trackEvent(TAG, "switched_tab", "videos", 1); 
     } else if (id == R.id.EvidenceListUploadTabButton) { 
      newUri = LocalEvidence.CONTENT_UPLOADED_URI; 
      newTitle = getString(R.string.tab_all_uploaded); 
      EasyTracker.getTracker().trackEvent(TAG, "switched_tab", "uploaded", 1); 
     } 

     //only change something if its a different view 
     if (!mData.equals(newUri) && newUri != null) { 
      mData = newUri; 
      changeCursor(); 
      setActiveButton(); 
      mTitleView.setText(newTitle); 
     } 
    } 
    public void changeView(View button) { 
     changeView(button.getId()); 
    } 

} 
+1

可能重複http://stackoverflow.com/questions/5278794/is-there-a-way-to-see-a-complete- stack-trace-from-android – Adi 2012-08-17 16:44:09

+0

不,這些錯誤通常是由此錯誤引起的更多錯誤,並且不會包含代碼中的哪一行導致崩潰。它看起來像它可能在你的onResume,你正在訪問一個不再有效的遊標的地方。 – Luke 2012-08-17 16:44:21

+0

這是一個完全有效的堆棧。你有一個託管光標,即使你手動關閉了光標。你應該發佈你的代碼 – nandeesh 2012-08-17 16:46:14

回答

0

有一個偉大的免費工具我用,BugSense這是很容易的插入到你的應用程序,當發生崩潰時它會告訴你,導致崩潰的行號。它還 通知您崩潰,給你關於Android版本,應用程序版本,previoius出現次數的數量,設備狀態,以及更多的信息。

這是從我的應用程序崩潰報告的例子: enter image description here

+0

我實際上使用bugsense ..但是,它不會包含任何信息比在由logcat AFAIK報告的錯誤跟蹤。 – 2012-08-17 16:59:54

+0

事實上,最近我的大部分崩潰日誌中有曾在我的代碼沒有相關的線,導致崩潰。這最新的一次是隻是一個讓我不高興,因爲它似乎在ICS /豆形軟糖相比更多的設備經常發生在薑餅和froyo上 – 2012-08-17 17:01:14

+0

是的。當它是一個運行時異常沒有行號, 但它確實給你有用的信息: 'android.database.StaleDataException:試圖訪問光標之後就已經closed.' 所以,你試圖訪問一個光標關閉後。 我建議您在使用光標的部分中調試代碼,然後您可以發現導致錯誤的原因 – 2012-08-17 17:02:44

相關問題