2016-01-04 3 views
1

J'ai une MultipartPostRequest avec une fonctionnalité de comptage de progression implémentée dans la méthode getBody(). Donc, je montre la progression dans la barre de notification. Et lorsque l'utilisateur clique sur la notification indiquant la progression, elle devrait être annulée, un peu comme la façon dont Facebook l'implémente.Une requête peut-elle être annulée lorsqu'elle est déjà dans la méthode getBody()?

J'ai essayé d'utiliser Request.cancel() sur l'objet Request actuel, et RequestQueue.cancelAll(Object tag) mais la demande n'est toujours pas annulée. J'ai lu qu'une demande en cours ne peut pas être annulée, mais dans ce cas, il est encore juste dans la méthode getBody(), donc je pense (je ne suis pas vraiment sûr) il devrait être annulé à droite? Comme j'ai également enregistré le retour de la méthode isCancelled() et oui il renvoie vrai lorsque la notification est cliquée, et le journal est appelé dans la méthode qui renvoie la progression de la demande de téléchargement, ce qui signifie qu'il est dans la méthode getBody().

Mais étonnamment, et frustrant, la demande continue malgré tout car elle renvoie toujours un résultat!

Y a-t-il un moyen de contourner cela? Ou y a-t-il un moyen de l'implémenter comme Facebook? Je donnerai volontiers une prime pour cela quand je le pourrai.

J'utilise la classe de cette réponse: https://stackoverflow.com/a/28144660/1744379

En raison de certaines circonstances, je ne peux pas partager mon code. Mais la classe est exactement ce que j'ai utilisé avec lequel j'ai juste fait quelques ajustements mineurs. Le placement du CountingOutputStream est le même que le CountingOutputStream et le MultipartPostProgressListener. Ainsi, le Log qui vérifie la méthode isCancelled est à l'intérieur de la méthode transferred que je mis en œuvre dans un Service

+0

Salut! Est-ce que ma réponse fonctionne pour votre question? – BNK

+0

Salut désolé le client a abandonné l'idée. Mais non, la réponse n'a malheureusement pas fonctionné. Ce qui a fonctionné, c'est qu'à la fin de la méthode getBody(), j'ai vérifié si la requête est déjà annulée par la méthode 'isCancelled' et ensuite je donnerais un' byte [] 'vide à la requête en laissant le serveur retourner un erreur pour moi et je le laisserais en silence –

+0

Dans mon projet d'exemple, lorsque cancelUpload appelé, le fichier a cessé de télécharger dans environ 3-5 secondes plus tard. Bien sûr, les données téléchargées sur le serveur restent toujours là (par exemple, un fichier de 2 Mo sera téléchargé environ 1 Mo) – BNK

Répondre

1

OMI, vous pouvez reporter aux sections suivantes:

Tout d'abord, les variables nécessaires:

public class MainActivity extends AppCompatActivity { 
    private Context mContext = this; 
    private Uri mFileUri; 
    private String mFilePath; 
    private ImageView mImagePreview; 
    private ProgressBar mProgressBar; 
    StringRequest mStringRequest; 
    private long mFileLength; 
    private MultipartProgressListener multipartProgressListener; 
    ... 

Supposons vous avez le code pour sélectionner le fichier image du dossier appareil photo (galerie) du téléphone et le chemin du fichier (mFilePath).

private void cancelUpload(){  
    mStringRequest.cancel(); 
} 

private void uploadFile(){ 
    mProgressBar.setProgress(0); 
    String url = "http://yourserver/fileupload"; 
    MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); 
    entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); 

    if (mFilePath != null) { 
     File file = new File(mFilePath); 
     if (file.exists()) { 
      mFileLength = file.length(); 
      FileBody fileBody = new FileBody(file); 
      entityBuilder.addPart("file", fileBody); 

      final HttpEntity httpEntity = entityBuilder.build(); 

      mStringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { 
       @Override 
       public void onResponse(String response) { 
        mFilePath = ""; 
        Log.i("Multipart", response); 
       } 
      }, new Response.ErrorListener() { 
       @Override 
       public void onErrorResponse(VolleyError error) { 
        Log.e("Multipart", error.toString()); 
       } 
      }) { 
       @Override 
       public String getBodyContentType() { 
        return httpEntity.getContentType().getValue(); 
       } 

       @Override 
       public byte[] getBody() throws AuthFailureError { 
        ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
        try { 
         //httpEntity.writeTo(bos); 
         httpEntity.writeTo(new CountingOutputStream(bos, mFileLength, 
           multipartProgressListener)); 
        } catch (IOException e) { 
         Log.e("Multipart", e.toString()); 
        } 
        return bos.toByteArray(); 

       } 
      }; 
      mStringRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 5, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); 
      VolleySingleton.getInstance(mContext).addToRequestQueue(mStringRequest); 
     } 
    } 
} 

Le code suivant est venu du lien dans votre question, je l'ai fait quelques mises à jour (s'il vous plaît remarquer qu'ils ne sont static plus)

public interface MultipartProgressListener { 
     void transferred(long transfered, int progress); 
    } 

    public class CountingOutputStream extends FilterOutputStream { 
     private final MultipartProgressListener progListener; 
     private long transferred; 
     private long fileLength; 

     public CountingOutputStream(final OutputStream out, long fileLength, 
            final MultipartProgressListener listener) { 
      super(out); 
      this.fileLength = fileLength; 
      this.progListener = listener; 
      this.transferred = 0; 
     } 

     public void write(byte[] b, int off, int len) throws IOException { 
      Log.i("isCanceled", String.valueOf(mStringRequest.isCanceled())); 
      if (!mStringRequest.isCanceled()) { 
       out.write(b, off, len); 
       if (progListener != null) { 
        this.transferred += len; 
        int prog = (int) (transferred * 100/fileLength); 
        this.progListener.transferred(this.transferred, prog); 
       } 
      } else { 
       Log.w("Multipart", "Request canceled!"); 
       out.flush(); 
       out.close(); 
      } 
     } 

     public void write(int b) throws IOException { 
      if (!mStringRequest.isCanceled()) { 
       out.write(b); 
       if (progListener != null) { 
        this.transferred++; 
        int prog = (int) (transferred * 100/fileLength); 
        this.progListener.transferred(this.transferred, prog); 
       } 
      } else { 
       Log.w("Multipart", "Request canceled!"); 
       out.flush(); 
       out.close(); 
      } 
     } 
    } 

P/S: vous devez sélectionner la taille grand fichier :)