Java 如何在Android上使用网络I/O

Java 如何在Android上使用网络I/O,java,android,Java,Android,以下课程的目的是从不同新闻网站的不同文章中获取文本。下面的版本是为Android设计的,但在运行时会引发NetworkOnMainThread异常。当我使用这个类的早期版本时,它是专门为在计算机上运行而设计的,它工作得很好,但我不确定网络I/O在Android上是如何工作的。我已经看到了一些关于这个主题的问题的其他答案,但我不明白为什么在Android中该程序会抛出异常,但在桌面上它运行良好。有人能解释一下吗 package com.example.user.helloworld; impor

以下课程的目的是从不同新闻网站的不同文章中获取文本。下面的版本是为Android设计的,但在运行时会引发NetworkOnMainThread异常。当我使用这个类的早期版本时,它是专门为在计算机上运行而设计的,它工作得很好,但我不确定网络I/O在Android上是如何工作的。我已经看到了一些关于这个主题的问题的其他答案,但我不明白为什么在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();
}
package com.example.user.helloworld;
导入android.content.Context;
导入android.net.ConnectivityManager;
导入android.net.NetworkInfo;
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.net.MalformedURLException;
导入java.net.URL;
导入java.net.URLConnection;
导入java.util.ArrayList;
导入org.jsoup.jsoup;
导入org.jsoup.nodes.Document;
导入org.jsoup.select.Elements;
公共类文章接收者{
private ArrayList newsArticles=新ArrayList();
private ArrayList newsLinks=new ArrayList();
公共物品接收者(整数,字符串链接){
如果(数量!=0){
接收新闻文章(numArticles,link);
}否则{
System.out.println(“错误:对“+link+”的numArticles请求不能等于0”);
}
}
private void receiveNewsArticles(整数,字符串URL地址){
URL rssUrl=null;
//如果连接到Internet
if(true){//isInternetAvailable()){
试一试{
//收集链接
rssUrl=新的URL(URL地址);
BufferedReader in=新的BufferedReader(新的InputStreamReader(rssUrl.openStream());
弦线;
//修复bbc垃圾网址
if(urlAddress.equals(Main.BBC_URL)){
numArticles++;
}

而((line=in.readLine())!=null&&newsLinks.size()您需要异步执行web服务连接。 我在项目中使用的是具有类ApiConnection和接口get response。示例:

Apiconnection类

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;}
    }

}
你唯一需要的就是将响应调整到你需要的其他对象


我希望这有助于

您需要在单独的线程中进行调用。AsyncTask、Loader、thread。。。。。
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();