2012-05-25 6 views
0

У меня есть следующая проблема. Я использую DropBox SDK для загрузки файла в Dropbox, который отлично работает. Когда файл загружается (внутри AsyncTask), индикатор ProgressDialog отображается с кнопкой отмены, но здесь все равно. То, что не работает, - это когда кнопка отмены нажата, возникает событие NetworkOnMainThreadException. Я новичок в программировании на Android, но я подозреваю, что он имеет какое-то отношение к ProgressDialog, который находится в конструкторе. Так как это не в части «doInBackground».Попытка обойти NetworkOnMainThreadException в AsyncTask из-за ProgressDialog

Попытка исправить это с помощью OnDismissListener и сделать аборт onDismiss, но все равно не повезло. Я получаю сообщение об ошибке, когда вызывается «mRequest.abort()». Заранее благодарим за любые ответы!

Так вот мой код

public class DropBoxUpload extends AsyncTask<Void, Long, Boolean> implements OnDismissListener { 

    private DropboxAPI<?> mApi; 
    private String mPath; 
    private File mFile; 

    private long mFileLen; 
    private UploadRequest mRequest; 
    private Context mContext; 
    private final ProgressDialog mDialog; 

    private String mErrorMsg; 


    public DropBoxUpload(Context context, DropboxAPI<?> api, String dropboxPath, File file) { 

     // We set the context this way so we don't accidentally leak activities 
     mContext = context.getApplicationContext(); 

     mFileLen = file.length(); 
     mApi = api; 
     mPath = dropboxPath; 
     mFile = file; 

     mDialog = new ProgressDialog(context); 
     mDialog.setMax(100); 
     mDialog.setMessage("Uploading " + file.getName()); 
     mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
     mDialog.setProgress(0); 
     mDialog.setButton("Cancel", new OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) { 
       // This will cancel the putFile operation 
       mDialog.dismiss(); 

      } 
     }); 
     mDialog.setCancelable(true); 
     mDialog.setOnDismissListener(this); 

     mDialog.show();   
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 

     try { 
      // By creating a request, we get a handle to the putFile operation, 
      // so we can cancel it later if we want to 
      FileInputStream fis = new FileInputStream(mFile); 
      String path = mPath + mFile.getName(); 
      mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(), 
        new ProgressListener() { 
       @Override 
       public long progressInterval() { 
        // Update the progress bar every half-second or so 
        return 500; 
       } 

       @Override 
       public void onProgress(long bytes, long total) { 
        publishProgress(bytes); 
       } 
      }); 

      if (mRequest != null) { 
       mRequest.upload(); 
       return true; 
      } 

     } catch (DropboxUnlinkedException e) { 
      // This session wasn't authenticated properly or user unlinked 
      mErrorMsg = "This app wasn't authenticated properly."; 
     } catch (DropboxFileSizeException e) { 
      // File size too big to upload via the API 
      mErrorMsg = "This file is too big to upload"; 
     } catch (DropboxPartialFileException e) { 
      // We canceled the operation 
      mErrorMsg = "Upload canceled"; 
     } catch (DropboxServerException e) { 
      // Server-side exception. These are examples of what could happen, 
      // but we don't do anything special with them here. 
      if (e.error == DropboxServerException._401_UNAUTHORIZED) { 
       // Unauthorized, so we should unlink them. You may want to 
       // automatically log the user out in this case. 
      } else if (e.error == DropboxServerException._403_FORBIDDEN) { 
       // Not allowed to access this 
      } else if (e.error == DropboxServerException._404_NOT_FOUND) { 
       // path not found (or if it was the thumbnail, can't be 
       // thumbnailed) 
      } else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) { 
       // user is over quota 
      } else { 
       // Something else 
      } 
      // This gets the Dropbox error, translated into the user's language 
      mErrorMsg = e.body.userError; 
      if (mErrorMsg == null) { 
       mErrorMsg = e.body.error; 
      } 
     } catch (DropboxIOException e) { 
      // Happens all the time, probably want to retry automatically. 
      mErrorMsg = "Network error. Try again."; 
     } catch (DropboxParseException e) { 
      // Probably due to Dropbox server restarting, should retry 
      mErrorMsg = "Dropbox error. Try again."; 
     } catch (DropboxException e) { 
      // Unknown error 
      mErrorMsg = "Unknown error. Try again."; 
     } catch (FileNotFoundException e) { 
     } 

     return false; 
    } 

    @Override 
    protected void onProgressUpdate(Long... progress) { 
     int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5); 
     mDialog.setProgress(percent); 
    } 

    @Override 
    protected void onPostExecute(Boolean result) { 
     mDialog.dismiss();   
    } 

    @Override 
    public void onDismiss(DialogInterface arg0) { 
     // TODO Auto-generated method stub 
     mRequest.abort(); 
    } 
} 

ответ

2

Вы не можете получить доступ к mRequest объект из основного потока пользовательского интерфейса, как это то, что несет ответственность за работу сети. Вот почему вы получаете NetworkOnMainThreadException, когда вы звоните mRequest.abort().

Вы должны изменить код таким образом, чтобы использовать AsyncTask.cancel в диалоговом увольнении и проверить isCancelled периодически в вашем doInBackground и вызвать mRequest.abort(), когда задача будет отменена.

+0

thx для вашего быстрого ответа! так как проверить на isCancelled «периодически»? как бы я сделал что-то подобное? –

+0

Обычно это делается в цикле. В вашем случае вы можете сделать это в методе 'onProgress'' ProgressListener', который вызывается периодически. – Rajesh

+0

Раджеш благодарит! Я просто положил его в метод doInBackground, и он работает как шарм. Еще раз спасибо! Я бы проголосовал за ваш ответ, но у меня нет репутации ;-) –

0

вы должны вызвать метод отменить, чтобы остановить ваш процесс загрузки.

ast.cancel(true); 

где аст Ваш объект AsyncTask

+0

спасибо за ваш ответ! –

Смежные вопросы