Android Studio 访问 Internet 时出错

Android Studio Error When Accessing the Internet

所以我一直在 Android 工作室为我的学校开发这个 android 应用程序,我想从学校的网站上获取内容。我用一段简单的代码获取数据,然后用Jsoup解析HTML文档。这是我放入 class 中的代码,然后我在 Main activity 中访问了该代码。由于我是初学者,请原谅糟糕的代码质量。

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class Website {


//Variables
private URL url;
private String text;


//Constructor
public Website(String url) {
    try{
        this.url=new URL(url);
    }catch(MalformedURLException e){

    }

}

public String getParseData(){
    return this.text;
}

public void receiveContent(String elementclass){
    String html;
    try{


        InputStream is = (InputStream) url.getContent();
        BufferedReader in =new BufferedReader(new InputStreamReader(is));
        StringBuffer sb = new StringBuffer();
        String line;


        while ((line = in.readLine()) != null){
            sb.append(line);
        }

        html=sb.toString();

        Document doc= Jsoup.parse(html);
        Elements content=doc.getElementsByClass(elementclass);
        this.text=content.text();
    } catch (IOException e) {

    }
}

}

所以当我通过我的 activity 执行代码时出现错误。我已经在 Eclipse 中测试了代码,它按预期工作。当我 运行 它在 Android 设备或​​模拟器上时,它崩溃并给出堆栈跟踪。当我删除代码或不调用 class 时,它工作正常。只有当我执行这段代码时,我才会在 receiveContent 方法中得到更具体的信息。

01-17 16:03:22.321    5195-5195/com.example.lazycody.rmhs_app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.lazycody.rmhs_app, PID: 5195
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.lazycody.rmhs_app/com.example.lazycody.rmhs_app.MainActivity}: android.os.NetworkOnMainThreadException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2438)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2497)
        at android.app.ActivityThread.access0(ActivityThread.java:168)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5678)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1166)
        at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
        at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
        at java.net.InetAddress.getAllByName(InetAddress.java:214)
        at com.android.okhttp.internal.Dns.getAllByName(Dns.java:28)
        at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:216)
        at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:122)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:390)
        at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:343)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
        at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
        at java.net.URLConnection.getContent(URLConnection.java:190)
        at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getContent(HttpsURLConnectionImpl.java:169)
        at java.net.URL.getContent(URL.java:455)
        at com.example.lazycody.rmhs_app.Websiteinfo.getContent(Websiteinfo.java:41)
        at com.example.lazycody.rmhs_app.MainActivity.onCreate(MainActivity.java:18)
        at android.app.Activity.performCreate(Activity.java:5586)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)

此外,这是我的清单。

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

<uses-feature android:name="android.hardware.wifi" />

<application
    android:allowBackup="true"
    android:icon="@drawable/school_logo"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".YoutubePage"
        android:label="@string/title_activity_youtube_page" >
    </activity>
</application>

我不知道我做错了什么或者为什么它在 Eclipse 中有效但在 Android 中无效。我真的需要一些帮助,因为我必须在星期二之前完成这个应用程序!所以任何事情都会有帮助,谢谢!!!!

问题是您正试图在主线程上执行网络操作。这是不允许的,以避免长时间的网络操作冻结主线程导致 UI 变得无响应。

您需要在后台执行该操作。您可以 AsyncTask 或单独的线程。

Android applications normally run entirely on a single thread by default the "UI thread" or "main thread"). This means anything your application is doing in the UI thread that takes a long time to complete can trigger the ANR dialog because your application is not giving itself a chance to handle the input event or intent broadcasts.

Therefore, any method that runs in the UI thread should do as little work as possible on that thread. In particular, activities should do as little as possible to set up in key life-cycle methods such as onCreate() and onResume(). Potentially long running operations such as network or database operations, or computationally expensive calculations such as resizing bitmaps should be done in a worker thread (or in the case of databases operations, via an asynchronous request).

The most effecive way to create a worker thread for longer operations is with the AsyncTask class. Simply extend AsyncTask and implement the doInBackground() method to perform the work. To post progress changes to the user, you can call publishProgress(), which invokes the onProgressUpdate() callback method. From your implementation of onProgressUpdate() (which runs on the UI thread), you can notify the user. For example:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    // Do the long-running work in here
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    // This is called each time you call publishProgress()
    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    // This is called when doInBackground() is finished
    protected void onPostExecute(Long result) {
        showNotification("Downloaded " + result + " bytes");
    }
}

To execute this worker thread, simply create an instance and call execute():

new DownloadFilesTask().execute(url1, url2, url3);

来源:Keeping Your App Responsive - How to Avoid ANRs