web-dev-qa-db-fra.com

Android - Android.os.NetworkOnMainThreadException

J'ai cette exception et je lisais un fil sur cela, et cela semblait déroutant:

Comment réparer Android.os.NetworkOnMainThreadException?

J'ai déjà ajouté cette ligne à mon manifeste:

<uses-permission Android:name="Android.permission.INTERNET" />

Dans cette discussion, ils parlent du principal fil d'exécution de l'application qui ne peut pas faire de réseau. Ce que je me demande, c'est comment restructurer mon code afin qu'il soit conforme aux bonnes pratiques d'Android.

Voici ma classe d'activité pour cela:

package com.problemio;

import Java.io.InputStream;
import Java.util.ArrayList;

import org.Apache.http.HttpEntity;
import org.Apache.http.HttpResponse;
import org.Apache.http.NameValuePair;
import org.Apache.http.client.HttpClient;
import org.Apache.http.client.entity.UrlEncodedFormEntity;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.Apache.http.message.BasicNameValuePair;

import Android.app.Activity;
import Android.content.Intent;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.Button;
import Android.widget.EditText;
public class LoginActivity extends Activity 
{
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);

        // Show form for login_email
        final EditText loginEmail = (EditText) findViewById(R.id.login_email);  
        String name = loginEmail.getText().toString();  

        // Show field for password  
        final EditText password = (EditText) findViewById(R.id.password);  
        String text = password.getText().toString();                  

        // Show button for submit
        Button submit = (Button)findViewById(R.id.submit);   




        // Show options for create-profile and forgot-password




        submit.setOnClickListener(new Button.OnClickListener() 
        {  
           public void onClick(View v) 
           {
              String email = loginEmail.getText().toString();
              String pass = password.getText().toString(); 
              sendFeedback(pass, email);
            }
        });        
    }


    public void sendFeedback(String pass , String email) 
    {  
        Log.d( "1" , pass );
        Log.d( "1" , email );

        // Go to db and check if these r legit
        // How do I do that? :)
        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();  
        postParameters.add(new BasicNameValuePair("username", email ));  
        postParameters.add(new BasicNameValuePair("password", pass ));

        String responseString = null;

        try 
        {  
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("myUrl");

            // no idea what this does :)
            httppost.setEntity(new UrlEncodedFormEntity(postParameters));

            // This is the line that send the request
            HttpResponse response = httpclient.execute(httppost);

            HttpEntity entity = response.getEntity();            

            InputStream is = entity.getContent();
        } 
        catch (Exception e) 
        {     
            Log.e("log_tag", "Error in http connection "+e.toString());
        }        
    }          
}

Qu'est-ce que je fais mal ici et comment pourrais-je résoudre le problème? :) Merci!!

47
GeekedOut

NetworkOnMainThreadException: Exception levée lorsqu'une application tente d'effectuer une opération de mise en réseau sur son thread principal.

Vous devriez appeler la méthode sendfeedback sur asynctask, alors seul le code ci-dessus fonctionnera. Comme le serveur Web prend beaucoup de temps pour répondre, le fil principal cesse de répondre. Pour l'éviter, vous devriez l'appeler sur un autre thread. Par conséquent, asynctask est meilleur. 

voici link qui illustre comment utiliser asynctask 

55
user1087919

NetworkOnMainThreadException est levé lorsque votre application tente une opération de mise en réseau dans le thread principal.

Pour résoudre ce problème, vous pouvez utiliser une classe interne privée au sein de votre activité qui étend Android.os.AsyncTask<Params, Progress, Result>, ce qui servira aux appels de serveur.

Quelque chose comme, 

private class SendfeedbackJob extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String[] params) {
        // do above Server call here
        return "some message";
    }

    @Override
    protected void onPostExecute(String message) {
        //process message
    }
}

Et puis invoquer la classe ci-dessus à partir de submit.setOnClickListener comme ci-dessous, 

SendfeedbackJob job = new SendfeedbackJob();
job.execute(pass, email);

AsyncTask

Références

AsyncTask doc

Exemple d'AsyncTask Android

32
prayagupd
if (Android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
10
AnDx
 try 
    {  
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("myUrl");

        // no idea what this does :)
        httppost.setEntity(new UrlEncodedFormEntity(postParameters));

        // This is the line that send the request
        HttpResponse response = httpclient.execute(httppost);

        HttpEntity entity = response.getEntity();            

        InputStream is = entity.getContent();
    } 
    catch (Exception e) 
    {     
        Log.e("log_tag", "Error in http connection "+e.toString());
    }        

Voici votre problème. Depuis api 11, cette exception vous informera que vous exécutez de longues tâches sur le thread d'interface utilisateur (la communication http de votre classe) et, conformément à la nouvelle stratégie StrictGuard, cela n'est pas possible. Donc, vous avez deux choix différents 

  1. Utilisez thread ou aynctask pour exécuter votre tâche à long terme (meilleur moyen)
8
Blackbelt

Vous pouvez simplement créer une classe async comme ci-dessous

class Retrievedata extends AsyncTask<String, Void, String> {
@Override
    protected String doInBackground(String... params) {
         try{
                //Your code 
                }
        return null;
    }
}

Vous pouvez simplement mettre tout votre code dans la méthode doInBackground

3
Kirtikumar A.

Vous avez fait un appel réseau sur le thread principal, ce qui est contraire aux règles Android. Vous devez donc effectuer votre appel réseau sur un thread séparé, comme un asyncte ou un gestionnaire, etc.

3
sankar

Après une longue recherche (une demi-journée), j'ai trouvé une solution à mon problème similaire au problème indiqué ici. L'exception affichée par mon Android Studio 2.3.3 était la suivante:

Android studio Android.os.networkonmainthreadexception

Le problème reposait sur l'impossibilité de définir une variable d'interface utilisateur dans MainActivity. J'ai donc vu la vidéo suivante et j'ai résolu mon problème. J'espère que c'est aussi utile aux autres:

Comment éviter Android OS NetworkOnMainThreadException

0
Remo Tomasi

Le thread principal est le thread d'interface utilisateur et vous ne pouvez pas effectuer d'opération dans le thread principal susceptible de bloquer l'utilisateur Interaction.Pour éviter cela, créez un simple gestionnaire et mettez à jour le thread principal si vous le souhaitez.

Runnable runnable;
Handler newHandler;

newHandler = new Handler();
runnable = new Runnable() {
    @Override
    public void run() {
        try {
            //update UI
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
};
runnable.run();

pour arrêter l'utilisation du fil

newHandler.removeCallbacks (exécutable);

Pour plus d'informations, regardez ceci. https://Android-developers.googleblog.com/2009/05/punset-threading.html

0
Anonymous

regardez ce lien: https://developer.Android.com/reference/Android/os/NetworkOnMainThreadException.html

Exception levée lorsqu'une application tente d'effectuer une opération de mise en réseau sur son thread principal . Les applications ciblant des versions antérieures du SDK sont autorisées à mettre en réseau leurs threads de boucle d'événements principaux, mais cela est fortement déconseillé.

si vous définissez minSdkVersion <11, votre application fonctionnera et vous pourrez exécuter une opération réseau dans le thread principal.

0
amin