2016-03-20 20 views
0

Ich bin neu bei Android und ich versuche, Daten von einem Server zu lesen. Ich benutze einen util und nennen das util wie dieseSo lösen Sie android.os.networkonmainthreadexception

private void ParseSource(String Url){ 
    String source = new Cls_SourceGrabber().grabSource(Url); 
} 

Aber ich bin immer ein android.os.networkonmainthreadexception. Wie kann ich das reduzieren?

Mein SourceGrabber util:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.URI; 
import java.net.URISyntaxException; 

import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.conn.ConnectTimeoutException; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 

public class Cls_SourceGrabber { 
    private HttpGet mRequest; 
    private HttpClient mClient; 
    private BufferedReader mReader; 

    private StringBuffer mBuffer; 
    private String mNewLine; 

    public Cls_SourceGrabber() { 
     mRequest = new HttpGet(); 
     InitializeClient(); 
     mReader = null; 

     mBuffer = new StringBuffer(10000); 
     mNewLine = System.getProperty("line.separator"); 
    } 

    private void InitializeClient() { 
     if (mClient == null || mClient.getConnectionManager() == null) { 
      HttpParams httpParameters = new BasicHttpParams(); 
      HttpConnectionParams.setConnectionTimeout(httpParameters, 4500); 
      HttpConnectionParams.setSoTimeout(httpParameters, 10000); 
      // HttpConnectionParams.setTcpNoDelay(httpParameters, true); 
      mClient = new DefaultHttpClient(httpParameters); 
     } 
    } 

    /* 
    *Grab the full source 
    */ 
    public String grabSource(String url) { 
     mBuffer.setLength(0); 
     InitializeClient(); 
     String source = ""; 
     try { 
      mRequest.setURI(new URI(url)); 
      HttpResponse response = mClient.execute(mRequest); 
      mReader = new BufferedReader(new InputStreamReader(response 
        .getEntity().getContent())); 

      String line = ""; 
      while ((line = mReader.readLine()) != null) { 
       mBuffer.append(line); 
       mBuffer.append(mNewLine); 
       source = mBuffer.toString(); 
       if (Thread.interrupted()) { 
        break; 
       } 
      } 
     } catch (ConnectTimeoutException e) { 
      source = "Connection Timed Out."; 
     } catch (java.net.UnknownHostException e) { 
      source = "No Internet Connection available!"; 
     } catch (java.lang.ArrayIndexOutOfBoundsException e) { 
      source = "Site Parsing Exception."; 
     } catch (ClientProtocolException e) { 
      source = "Protocol Exception."; 
     } catch (IOException e) { 
      source = "Server not responding."; 
     } catch (URISyntaxException e) { 
      source = "Wrong URL!"; 
     } catch (Exception e) { 
      source = "Exception - " + e.toString() + " - " 
        + e.getMessage(); 
      e.printStackTrace(); 

     } finally { 
      closeReader(); 
     } 
     return source; 
    } 

} 
+2

Mögliche Duplikat [? Wie beheben android.os.NetworkOnMainThreadException] (http://stackoverflow.com/questions/6343166/how-to-fix-android-os- networkonmainthreadexception) –

+1

Führen Sie Ihren Netzwerkcode in der asynchronen Taskklasse oder im Dienst aus. Sie sollten keinen Netzwerkcode im Hauptthread schreiben. – Talha

Antwort

0

Zunächst einmal würde ich nicht empfehlen Httpclient über die Verwendung nicht mehr, da sie nicht unterstützt wird nicht mehr von sdk Version 23.

So wird es sein besser, um die Netzwerkoperationen auf URL-Verbindung zu migrieren.

Jetzt erlaubt Netzwerk nie Operationen auf Haupt-Thread, da es den UI-Thread für eine beträchtliche Zeit blockiert, daher kann zum Absturz oder schlechte Benutzererfahrung führen.

Sie können einen Blick auf diese Dokumente nehmen: Doc 1

Der bessere Weg Netzwerk-Operationen zu tun ist durch eine AsyncTask zu schaffen.

Achten Sie darauf, dass Sie in der doInBackground-Methode nicht auf ein UI-Thread-Element zugreifen. Sie können UI-Thread-Elemente in onPreExecute- oder onPostExecute-Methoden ändern.

Ich habe eine NetworkOps Util erstellt. Sie können einen Blick auf das nehmen, ob es für Sie Nutzen sein kann:

import android.content.Context; 
import android.net.Uri; 
import android.util.Log; 

import com.csehelper.variables.Constants; 
import com.csehelper.variables.Keys; 
import com.csehelper.variables.Url; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.net.HttpURLConnection; 
import java.net.ProtocolException; 
import java.net.SocketTimeoutException; 
import java.net.URL; 
import java.util.ArrayList; 

public class NetworkOps { 
    public final String EXCEPTION = "~Exception~"; 
    /**************************** 
    * Method to Grab Source 
    ****************************/ 
    public static String GrabSource(String URL) { 
     return PostData(URL, null); 
    } 



    /** 
    * ***************************************** 
    * Method to Grab Source code from URL 
    * Posting Data 
    * ***************************************** 
    */ 
    private static String PostData(String url, Uri.Builder uribuilder) { 
     String Source; 
     HttpURLConnection.setFollowRedirects(false); 
     HttpURLConnection urlConnection = null; 
     try { 
      urlConnection = (HttpURLConnection) new URL(url).openConnection(); 
      urlConnection.setDoOutput(true); 
      urlConnection.setConnectTimeout(10000); 

      if(uribuilder != null) { 
       String query = uribuilder.build().getEncodedQuery(); 

       OutputStream os = urlConnection.getOutputStream(); 
       BufferedWriter writer = new BufferedWriter(
         new OutputStreamWriter(os, "UTF-8")); 
       writer.write(query); 
       writer.flush(); 
       writer.close(); 
       os.close(); 
      } 

      urlConnection.connect(); 

      if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { 

       String line; 
       StringBuilder builder = new StringBuilder(); 
       InputStreamReader isr = new InputStreamReader(
         urlConnection.getInputStream()); 
       BufferedReader reader = new BufferedReader(isr); 
       while ((line = reader.readLine()) != null) { 
        builder.append(line); 
       } 
       Source = builder.toString(); 
      } else { 
       Source = EXCEPTION + "Server unreachable. Check network connection."; 
      } 
     } catch (SocketTimeoutException e) { 
      Source = EXCEPTION + "Connection timed out."; 
     } catch (java.net.UnknownHostException e) { 
      Source = EXCEPTION + Constants.EXCEPTION_NO_NET; 
     } catch (ArrayIndexOutOfBoundsException e) { 
      Source = EXCEPTION + "Server error"; 
     } catch (ProtocolException e) { 
      Source = EXCEPTION + "Protocol error"; 
     } catch (IOException e) { 
      Source = EXCEPTION + "Server unreachable. Check network connection."; 
     } catch (Exception e) { 
      Source = EXCEPTION + "Error:" + e.toString() + " - " 
        + e.getMessage(); 
      e.printStackTrace(); 

     } finally { 
      if (urlConnection != null) urlConnection.disconnect(); 
     } 
     return Source; 
    } 


} 

Rufen Sie diese statischen Funktionen von AsyncTask:

/********************************* 
* AsyncTask to GrabSource 
********************************/ 
class AsyncTask_GrabSource extends AsyncTask<Void, Void, Void> { 

    String Source = null; 
    String url = "https://enigmatic-woodland-35608.herokuapp.com/pager.json"; 
    @Override 
    protected void onPreExecute() { 
     //Runs on Main Thread. You can access your UI elements here. 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     // Don't access any UI elements from this function 
     Source = NetworkOps.GrabSource(this.url); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     if (Source != null) { 
      if (!Source.contains("~Exception~")) { 
       //Show Error Message or do whatever you want 
      } else { 
       //Do Whatever with your Grabbed Sourcecode. 
       // This function runs on UI Thread, so you can update UI elements here 
      } 

    } 
} 

Sie auch Daten mit der Funktion Postdata veröffentlichen können. In Verfahren doInBackground, fügen Sie diese:

Uri.Builder builder = new Uri.Builder() 
        .appendQueryParameter("key", "value") 
        .appendQueryParameter("key2", "value2"); 

Source = NetworkOps.PostData(getApplicationContext(), url, builder); 
+0

Vielen Dank. Eigentlich hast du mein Leben vor meinem Vorgesetzten gerettet :-) –

Verwandte Themen