简体   繁体   中英

Saving webpage to external storage crashes the app

I'm trying to save a webpage to my external storage with the following method:

public void saveWebPage(String url, String fileName){
    try {
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response;
        response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        InputStream is = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null){
            sb.append(line + "\n");
        }
        String resString = sb.toString();
        is.close();
        File file = new File(Environment.getExternalStorageDirectory().toString() + "/Android/data/com.whizzapps.stpsurniki/" + fileName + ".html");
        file.createNewFile();
        FileOutputStream f1 = new FileOutputStream(file, false);
        PrintStream p = new PrintStream(f1);
        p.print(resString);
        p.close();
        f1.close();
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

When I call the method, the app crashes and this is the logcat:

09-09 17:26:22.304: E/AndroidRuntime(14507): FATAL EXCEPTION: main
09-09 17:26:22.304: E/AndroidRuntime(14507): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.whizzapps.stpsurniki/com.whizzapps.stpsurniki.Scheudele}: android.os.NetworkOnMainThreadException
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.ActivityThread.access$600(ActivityThread.java:141)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.os.Handler.dispatchMessage(Handler.java:99)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.os.Looper.loop(Looper.java:137)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.ActivityThread.main(ActivityThread.java:5103)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at java.lang.reflect.Method.invokeNative(Native Method)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at java.lang.reflect.Method.invoke(Method.java:525)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at dalvik.system.NativeStart.main(Native Method)
09-09 17:26:22.304: E/AndroidRuntime(14507): Caused by: android.os.NetworkOnMainThreadException
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1133)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at java.net.InetAddress.getAllByName(InetAddress.java:214)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at com.whizzapps.stpsurniki.Scheudele.saveWebPage(Scheudele.java:135)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at com.whizzapps.stpsurniki.Scheudele.getWebView(Scheudele.java:66)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at com.whizzapps.stpsurniki.Scheudele.onCreate(Scheudele.java:50)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.Activity.performCreate(Activity.java:5133)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-09 17:26:22.304: E/AndroidRuntime(14507):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
09-09 17:26:22.304: E/AndroidRuntime(14507):    ... 11 more

I was told to put this in UI Thread but I don't know in which line of code the ui thread is. I simply put it next to other methods in the activity class file.

New code:

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

    @Override
    protected Void doInBackground(String... params) {
        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            HttpResponse response;
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null){
                sb.append(line + "\n");
            }
            String resString = sb.toString();
            is.close();
            File file = new File(Environment.getExternalStorageDirectory().toString() + "/Android/data/com.whizzapps.stpsurniki/" + fileName + ".html");
            file.createNewFile();
            FileOutputStream f1 = new FileOutputStream(file, false);
            PrintStream p = new PrintStream(f1);
            p.print(resString);
            p.close();
            f1.close();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

The exception clearly indicates android.os.NetworkOnMainThreadException , which means you should always make Network call only in a seperate thread.

Solution: Create a new thread, and do Network call.

You can use AsyncTask , The AsyncTask class provides one of the simplest ways to fire off a new task from the UI thread from Android documentation

See the android link for more information.


Read the documentation about AsyncTask carefully.

The three types used by an asynchronous task are the following:

  1. Params, the type of the parameters sent to the task upon execution.
  2. Progress, the type of the progress units published during the background computation.
  3. Result, the type of the result of the background computation

In your case, you should use Params to send parameter to the method (eg url and filename)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM