7
votes

Comment débloquer InputStream.Read () sur Android?

J'ai un fil dans lequel le lue () méthode d'un INPUTStream est appelé dans une boucle. Lorsqu'il n'y a plus d'octets à lire, le flux bloquera jusqu'à ce que de nouvelles données arrivent.

Si j'appelle fermeture () sur le INPUTStream à partir d'un autre fil, le flux est fermé, mais le bloqué () appel reste toujours bloqué. Je supposerais que la méthode lue () doit maintenant revenir avec une valeur de -1 pour indiquer la fin du flux, mais ce n'est pas le cas. Au lieu de cela, il reste bloqué pendant plusieurs minutes jusqu'à ce qu'un délai de TCP se produise.

Comment puis-je débloquer le ferme () appel?

EDIT:

Apparemment, le jre régulier jettera un SocketException immédiatement lorsque le flux ou la prise Le blocage Lecture () L'appel correspond à IS Fermer () 'd. Le temps d'exécution Android Java que j'utilise, cependant, ne sera pas.

Toute astuce sur une solution pour l'environnement Android serait grandement appréciée.


1 commentaires

Je ne suis pas un gars Java, mais si vous contrôlez l'application / thread en envoyant le flux, ne pourriez-vous pas envoyer d'octet / couple d'octets de fin de message que le lecteur peut utiliser pour déterminer que le flux doit être fermé ?


6 Réponses :


1
votes

Vous pouvez utiliser package java.nio . Nio signifie IO non bloquante. Ici, les appels (pour dire que lire et écrire) ne sont pas bloqués. De cette façon, vous pouvez fermer le flux.

Il existe un exemple de programme que vous pouvez regarder ici . Méthode: ProcurentRead


0 commentaires

4
votes

seul appel lecture () quand il y a des données disponibles.

faire quelque chose comme ça: xxx

Définir le fichier pour arrêter la lecture.


5 commentaires

Disponible () ne vous indiquera que si des données sont disponibles sans effectuer un appel système. Cela peut renvoyer 0 quand il y a des données à lire.


D'accord. C'est exactement ce que j'avais auparavant. Il utilise beaucoup de CPU, cependant, comme la boucle tourne constamment. Je pensais que l'utilisation d'un bloc d'E / S serait remédier à ce problème.


Vous pouvez ajouter un veille comme dernière ligne de votre boucle. Cela vous empêchera de vous occuper d'attendre


Cette solution n'est pas la plus élégante, mais la seule que je dois travailler correctement sur Android.


Notez que les documents Android pour la disponibilité () commencent par l'avertissement "Notez que cette méthode offre une garantie si faible qu'il n'est pas très utile dans la pratique."



3
votes

Lorsque l'autre extrémité ferme la connexion, votre flux retournera -1 sur une lecture (). Si vous ne pouvez pas déclencher l'autre extrémité pour fermer la connexion E.G. En fermant votre flux de sortie, vous pouvez fermer la prise qui provoquera une impression IoException dans le thread de lecture () de blocage ().


Pouvez-vous fournir un court exemple qui reproduit votre problème? P>

104
105
10
java.net.SocketException: Socket closed


3 commentaires

C'est ce que je pensais. Mais je ne reçois pas d'exception. La lecture () continue de bloquer même si la prise est fermée.


Merci pour l'exemple de code Nice! L'échantillon fonctionne bien lors de la compilation comme une application Java régulière. L'appui à une application Android Bones Bones révèle que l'exception n'est apparemment pas lancée, même si les mêmes classes Java.net sont utilisées. Donc, le problème réside dans Android, je suppose. Une idée?


J'ai pris la liberté d'ajouter Android en tant que balise car cela semble être un détail clé. ;)



3
votes

voir Java Concurrence dans la pratique pour un très bon système à Annuler un fil lorsque vous travaillez avec des sockets. Il utilise un exécutant spécial ( CanchingElexEcutor ) et un appel téléphonique spécial ( SockingTask ).


0 commentaires

2
votes

Nous avions le même problème: aucune exception lors de la commutation réseau (par exemple, passer de 3G en wifi lors du téléchargement).

Nous utilisons le code de http://www.androidsnippets.com/download-an-http-file-a-sdcard-with-progresse- Notification , qui fonctionne parfaitement sauf dans certains cas lorsque la connexion réseau a été perdue.

La solution spécifiait une valeur de délai d'attente, ceci est défini en standard sur 0 (Signification: attendre infiniment). < / p> xxx

expérience avec une valeur de délai d'expiration appropriée pour vous.


0 commentaires

2
votes

J'ai eu un tel problème sur Samsung 2.3. Lors de la passation des blocs de méthode () de la méthode (). J'ai essayé tous les conseils de ce sujet. Rien n'a aidé. De mon éventuel éventuel, c'est un problème spécifique au dispositif, car devrait strong> lancer ioException en raison de Javadoc . Ma solution consiste à écouter pour Android Broadcast android.net.conn.connecity_change A> et une connexion rapprochée d'un autre thread, il provoquera une exception ioexception dans un fil bloqué.

Voici l'exemple de code: p>

downloadthread.java p>

private volatile boolean canceled;

private volatile InputStream in;

private boolean downloadFile(final File file, final URL url, long totalSize) {
    OutputStream out = null;
    try {
        Log.v(Common.TAG, "DownloadThread: downloading to " + file);

        in = (InputStream) url.getContent();
        out = new FileOutputStream(file);

        return copy(out, totalSize);
    } catch (Exception e) {
        Log.e(Common.TAG, "DownloadThread: Exception while downloading. Returning false ", e);
        return false;
    } finally {
        closeStream(in);
        closeStream(out);
    }
}

public void cancelDownloading() {
    Log.e(Common.TAG, "DownloadThread: cancelDownloading ");
    canceled = true;
    closeStream(in); //on my device this is the only way to unblock thread
}

private boolean copy(final OutputStream out, long totalSize) throws IOException {
    final int BUFFER_LENGTH = 1024;
    final byte[] buffer = new byte[BUFFER_LENGTH];
    long totalRead = 0;
    int progress = 0;
    int read;

    while (!canceled && (read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
        totalRead += read;
    }
    return !canceled;
}


0 commentaires