2016-07-29 5 views
-1

Der Zweck der folgenden Klasse besteht darin, Text aus verschiedenen Artikeln verschiedener Nachrichtenwebsites zu erhalten. Die folgende Version ist für Android konzipiert, löst jedoch eine NetworkOnMainThread-Ausnahme aus, wenn sie ausgeführt wird. Als ich eine frühere Version dieser Klasse verwendet habe, die speziell für die Ausführung auf einem Computer entwickelt wurde, funktionierte es gut, aber ich bin mir nicht sicher, wie Netzwerk-I/O auf Android funktioniert. Ich habe einige andere Antworten auf Fragen zu diesem Thema gesehen, aber ich verstehe nicht, warum das Programm in Android eine Ausnahme auslöst, aber auf einem Desktop funktioniert es gut. Kann mir jemand erklären?So verwenden Sie Netzwerk-E/A mit Android

package com.example.user.helloworld; 

import android.content.Context; 
import android.net.ConnectivityManager; 
import android.net.NetworkInfo; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLConnection; 
import java.util.ArrayList; 

import org.jsoup.Jsoup; 
import org.jsoup.nodes.Document; 
import org.jsoup.select.Elements; 

public class ArticleReceiver { 

private ArrayList<Article> newsArticles = new ArrayList<>(); 
private ArrayList<String> newsLinks = new ArrayList<>(); 

public ArticleReceiver(int numArticles, String link) { 
    if (numArticles != 0) { 
     receiveNewsArticles(numArticles, link); 
    }else{ 
     System.out.println("ERROR: numArticles request for " + link + " cannot equal 0."); 
    } 
} 

private void receiveNewsArticles(int numArticles, String urlAddress) { 
    URL rssUrl = null; 
    // if connected to Internet 
    if (true){//isInternetAvailable()) { 
     try { 
      // gather links 
      rssUrl = new URL(urlAddress); 
      BufferedReader in = new BufferedReader(new InputStreamReader(rssUrl.openStream())); 
      String line; 

      // fix bbc trash urls 
      if (urlAddress.equals(Main.BBC_URL)) { 
       numArticles++; 
      } 

      while ((line = in.readLine()) != null && newsLinks.size() <= numArticles) { 
       if (line.contains("<link>")) { 
        // find links through tags 
        int firstPos = line.indexOf("<link>"); 
        String temp = line.substring(firstPos); 
        temp = temp.replace("<link>", ""); 
        int lastPos = temp.indexOf("</link>"); 
        temp = temp.substring(0, lastPos); 

        newsLinks.add(temp); 
       } 
      } 

      in.close(); 

      // test if there are links and if there is remove first 
      // unnecessary 
      // link 
      if (!newsLinks.isEmpty()) { 
       if (urlAddress.equals(Main.BBC_URL)) { 
        newsLinks.remove(0); 
        newsLinks.remove(0); 
       }else if(urlAddress.equals(Main.CNN_URL) || urlAddress.equals(Main.FOX_URL) || urlAddress.equals(Main.ESPN_URL)){ 
        newsLinks.remove(0); 
       } 
      } else { 
       System.out.println("ERROR: No Found Articles. Check If You Have Wifi."); 
      } 

      // gather articles from HTML "section" or "p" tag of article using Jsoup 
      for (String newsLink : newsLinks) { 
       // get webpage 
       Document doc = Jsoup.connect(newsLink).get(); 

       // get article from different websites 
       String article = null; 
       if (urlAddress.equals(Main.FOX_URL)) { 
        Elements element = doc.select("p"); 
        article = element.text(); 
       } else if (urlAddress.equals(Main.CNN_URL)) { 
        Elements element = doc.select("section"); 
        article = element.text(); 
       } else if (urlAddress.equals(Main.BBC_URL)) { 
        Elements element = doc.select("p"); 
        article = element.text(); 
       }else if(urlAddress.equals(Main.ESPN_URL)){ 
        Elements element = doc.select("p"); 
        article = element.text(); 
       } 

       newsArticles.add(new Article(article, Main.SUMMARY_SENTENCES)); 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } else { 
     System.out.println("ERROR: No internet connection established."); 
     return; 
    } 
} 

public ArrayList<Article> getArticles() { 
    return newsArticles; 
} 

public Article getArticle(int i) { 
    if (newsArticles.size() <= i) { 
     return null; 
    } else { 
     return newsArticles.get(i); 
    } 
} 

//The method below does not recognize the "getSystemService" method, and when the method is no longer present there is a NetworkOnMainThreadException 
private boolean isInternetAvailable() { 
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); 
    return activeNetworkInfo != null && activeNetworkInfo.isConnected(); 
} 

}

+3

Sie müssen die Anrufe in separaten Thread zu machen. AsyncTask, Loader, Thread ..... –

Antwort

0

Sie müssen Web-Service-Verbindungen asynchron auszuführen. Was ich in meinen Projekten verwende, ist eine Klasse ApiConnection und mit Schnittstelle erhalten Antwort. Beispiel:

Apiconnection Klasse

public class APIConnection extends AsyncTask<Object, String, Void> { 

    private final String TAG = "API-CONNECTION"; 
    private StringBuilder sbuilder; 
    private JSONObject json; 
    private APIConnectionInterface mInterface; 
    protected int httpResponseCode = 0; 
    private String entity = null, url; 
    private APIConnectionType mmode; 
    private boolean DEBUG = BuildConfig.DEBUG; 

    private String[][] headers; 

    /** 
    Constructor For APIConnection 
    */ 
    public APIConnection(APIConnectionInterface thisdelegate, APIConnectionType mode, String murl, String entity) { 
     this.mInterface  = thisdelegate; 
     this.mmode   = mode; 
     this.url   = murl; 
     this.entity   = entity; 
     initHeaders(); 
    } 

    private void initHeaders(){ 
      headers = new String[][]{ 
        {"token", "MY_TOKEN"}, 
        {"Content-Type", "application/json;charset=utf-8"}, 
        {"user-agent", "android"}, 
        {"Accept-Language", "es"} 
      }; 
    } 

    @Override 
    protected Void doInBackground(Object... params) { 
     BufferedReader buffer = null; 
     InputStreamReader in = null; 
     OutputStream os = null; 

     int timeoutConnection = 30000, timeoutSocket = 20000; 

     try{ 
      sbuilder = new StringBuilder(); 

      url = convertURL(url); 
      if (entity==null)entity="{}"; 
      URL u = new URL(url); 
      HttpURLConnection conn; 
      if (url.startsWith("https://")) 
     conn = (HttpsURLConnection) u.openConnection(); 
      else 
     conn = (HttpURLConnection) u.openConnection(); 

      conn.setReadTimeout(timeoutConnection); 
      conn.setConnectTimeout(timeoutSocket); 

      for (String[] arr : headers){ conn.addRequestProperty(arr[0], arr[1]); } 

    /*GET*/if (mmode == APIConnectionType.GET) { 
       conn.setDoInput(true); 
       conn.setRequestMethod(mmode.toString()); 
       httpResponseCode = conn.getResponseCode(); 

       in = new InputStreamReader(
         httpResponseCode == HttpURLConnection.HTTP_OK ? conn.getInputStream() : conn.getErrorStream(),"UTF-8"); 

    /*OTHER*/} else if (mmode == APIConnectionType.POST || mmode == APIConnectionType.PUT || 
        mmode == APIConnectionType.PATCH || mmode == APIConnectionType.DELETE) { 

        conn.setRequestMethod(mmode.toString()); 
        conn.setDoOutput(true); 

        byte[] outputInBytes = entity.getBytes("UTF-8"); 
        os = conn.getOutputStream(); 
        os.write(outputInBytes); 

        httpResponseCode = conn.getResponseCode(); 

        in = new InputStreamReader(
          httpResponseCode == HttpURLConnection.HTTP_OK ? conn.getInputStream() : conn.getErrorStream(), "UTF-8"); 
      } 
      if (in!=null){ 
       buffer=new BufferedReader(in); 
       String line; 
       while ((line = buffer.readLine()) != null) { 
        sbuilder.append(line); 
       } 
      }else { 
       sbuilder.append(""); 
      } 

     } 
     catch(IOException e) { 
      if (DEBUG)Log.d(TAG, "onBackground Exception " + e.getMessage()); 
      sbuilder= new StringBuilder(); 
      httpResponseCode = 0; 
      cancel(true); 
      return null; 
     } finally { 
      if (buffer != null) { 
       try { 
        buffer.close(); 
       } catch (IOException ioe) { 
        ioe.printStackTrace(); 
       } 
      } 
      if (os!=null){ 
       try { 
        os.flush(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
       try { 
        os.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result){ 
     try{ 
      if (DEBUG) timelapse_e = System.currentTimeMillis(); 
      if (sbuilder != null) { 
        json = new JSONObject(sbuilder.toString()); 

      } 

      if (sbuilder != null){ 
       sbuilder.setLength(0); 
       sbuilder.trimToSize(); 
      } 

      sbuilder = null; 
      GoRunning(); 
      hideDialog(); 
     } 
     catch(RuntimeException e) { 
      if (DEBUG)Log.d(TAG, "PostExecute RuntimeException " + e.getMessage()); 
      cancel(true); 
     } 
     catch(Exception e) { 
      if (DEBUG)Log.d(TAG, "PostExecute Exception " + e.getMessage()); 
      cancel(true); 
     } 

    } 

    @Override protected void onCancelled() { 
     if (mInterface != null) mInterface.onCancelled(APIConnection.this); 
     super.onCancelled(); 
    } 

    @Override protected void onPreExecute() { 
     super.onPreExecute(); 
     if (DEBUG) timelapse_s = System.currentTimeMillis(); 
     if (mInterface != null) mInterface.onStartLoading(APIConnection.this); 
    } 

    public void GoRunning(){ 
     if (mInterface != null) try { 
      mInterface.onDataArrival(APIConnection.this, json, httpResponseCode); 
     } catch (JSONException e) { 
      onCancelled(); 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Hide Dialog (Progress dialog) if is showing and activity NOT Finishing 
    */ 
    private void hideDialog() { 
     if (mInterface != null) mInterface.onFinishedLoading(APIConnection.this); 
    } 

    /** <b>convertURL(String str);</b><br/> 
    * replaces any special characters to <b>%??</b><br/> 
    * Replacements actived:<br/> 
    * "{Space}" ==> "%20" 
    * @param str URL to encode 
    * @return url encoded 
    */ 
    public static String convertURL(String str) { 

     return str.trim().replace(" ", "%20"); 
      //    .replace("&", "%26") 
      //    .replace(",", "%2c").replace("(", "%28").replace(")", "%29") 
      //    .replace("!", "%21").replace("=", "%3D").replace("<", "%3C") 
      //    .replace(">", "%3E").replace("#", "%23").replace("$", "%24") 
      //    .replace("'", "%27").replace("*", "%2A").replace("-", "%2D") 
      //    .replace(".", "%2E").replace("/", "%2F").replace(":", "%3A") 
      //    .replace(";", "%3B").replace("?", "%3F").replace("@", "%40") 
      //    .replace("[", "%5B").replace("\\", "%5C").replace("]", "%5D") 
      //    .replace("_", "%5F").replace("`", "%60").replace("{", "%7B") 
      //    .replace("|", "%7C").replace("}", "%7D")); 
    } 

    public interface APIConnectionInterface { 
     void onDataArrival(APIConnection apiConnection, JSONObject json, int httpResponseCode) throws JSONException; 
     void onStartLoading(APIConnection apiConnection); 
     void onFinishedLoading(APIConnection apiConnection); 
     void onCancelled(APIConnection apiConnection); 
    } 

    public enum APIConnectionType { 
     GET("GET"), 
     POST("POST"), 
     PUT("PUT"), 
     PATCH("PATCH"), 
     DELETE("DELETE"); 
     private String methodName; 
     APIConnectionType(String methodName){this.methodName = methodName;} 
     @Override public String toString() {return methodName;} 
    } 

} 

Und dann von jeder Aktivität oder Fragment kann ich die Asynchron-Web-Service rufen

wie folgt aus:

new APIConnection(new APIConnection.APIConnectionInterface() { 
      @Override public void onDataArrival(APIConnection apiConnection, JSONObject json, int httpResponseCode) { 
       try { 
        if (isHttpResponseOk(httpResponseCode, json)){//200 or 201 

         JSONObject obj = json.getJSONObject("results"); 
         // do things with json 

        } 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
      } 
      @Override public void onStartLoading(APIConnection apiConnection) {showProgressDialog();} 
      @Override public void onFinishedLoading(APIConnection apiConnection) {hideProgressDialog();} 
      @Override public void onCancelled(APIConnection apiConnection) {hideProgressDialog();} 
     }, APIConnection.APIConnectionType.GET, MyApp.API_URL + "/master_data/", null).execute(); 

Das einzige, was Sie brauchen, ist zu Passen Sie die Antwort an andere Objekte an, die Sie benötigen.

Ich hoffe, dass hilft