Android数据下载实验

时间:2013-02-08 03:46:26

标签: android http exception

我对Android比较陌生,我正在尝试关注this教程。

我使用以下代码创建了一个小项目:

package com.example.revivaltimesv1;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private static final int LENGTH_LONG = 10;
    private TextView message;// = (TextView)findViewById(R.id.message);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        message = (TextView)findViewById(R.id.message);

        Log.i("mine", "TESTING ... TESTING!!!");

        ConnectivityManager conManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = conManager.getActiveNetworkInfo();
        if( networkInfo != null && networkInfo.isConnected() ){
            Toast.makeText(this, "Established Network Connection!", LENGTH_LONG).show();
            String stringURL = "http://178.79.128.76/GTK/node/7";
            new DownloadStuff().execute(stringURL);
//          new test().execute();
            //message.setText("WORKING");
        }else{
            Toast.makeText(this, "No Network Connection!", LENGTH_LONG).show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

//}

/*    private class test extends AsyncTask<String, String, String>{
        @Override
        protected String doInBackground(String... params) {
            // TODO Auto-generated method stub
            return null;
        }
    }
*/
    private class DownloadStuff extends AsyncTask<String, String, String>{

        protected String doInBackground(String... url) {
            // TODO Auto-generated method stub
            Log.i("CHECK", "OUTSIDE");
            try{
                Log.i("CHECK", "SUCCESS: " + url[0]);
                downloadUrl(url[0]);
                Toast.makeText(getApplicationContext(), "WORKING !!!", LENGTH_LONG).show();
            }catch(IOException i){
                Log.i("CHECK", "NOT so successful");
                Toast.makeText(getApplicationContext(), "ERROR: unable to establish contact with URL", LENGTH_LONG).show();     
            }
            return null;
        }

        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
//          super.onPostExecute(result);
            message.setText("Hurray!");
        }

        // Given a URL, establishes an HttpUrlConnection and retrieves
        // the web page content as a InputStream, which it returns as
        // a string.
        private String downloadUrl(String myurl) throws IOException {
            InputStream is = null;
            // Only display the first 500 characters of the retrieved
            // web page content.
            int len = 500;

            try {
                URL url = new URL(myurl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(10000 /* milliseconds */);
                conn.setConnectTimeout(15000 /* milliseconds */);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                // Starts the query
                conn.connect();
                int response = conn.getResponseCode();
                Log.d("DEBUG_TAG", "The response is: " + response);
                is = conn.getInputStream();

                // Convert the InputStream into a string
                String contentAsString = readIt(is, len);
                return contentAsString;

            // Makes sure that the InputStream is closed after the app is
            // finished using it.
            } finally {
                if (is != null) {
                    is.close();
                } 
            }
        }
        public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
            Reader reader = null;
            reader = new InputStreamReader(stream, "UTF-8");        
            char[] buffer = new char[len];
            reader.read(buffer);
            return new String(buffer);
        }
    }

}

该应用程序工作正常,但然后崩溃给我以下反馈:

02-08 03:39:16.316: E/AndroidRuntime(5106): FATAL EXCEPTION: AsyncTask #1
02-08 03:39:16.316: E/AndroidRuntime(5106): java.lang.RuntimeException: An error occured while executing doInBackground()
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.lang.Thread.run(Thread.java:1102)
02-08 03:39:16.316: E/AndroidRuntime(5106): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.os.Handler.<init>(Handler.java:121)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.widget.Toast.<init>(Toast.java:68)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.widget.Toast.makeText(Toast.java:231)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at com.example.revivaltimesv1.MainActivity$DownloadStuff.doInBackground(MainActivity.java:74)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at com.example.revivaltimesv1.MainActivity$DownloadStuff.doInBackground(MainActivity.java:1)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
02-08 03:39:16.316: E/AndroidRuntime(5106):     ... 4 more

我查看了错误堆栈的底部,但 ... 4 more 似乎隐藏了与我的代码相关的部分 - 我认为。

5 个答案:

答案 0 :(得分:1)

实际上,错误在logcat stacktrace中清晰显示:02-08 03:39:16.316: E/AndroidRuntime(5106): at com.example.revivaltimesv1.MainActivity$DownloadStuff.doInBackground(MainActivity.java:74)

理想情况下,Toasts / UI功能应在onPostExecute()中完成。但是,如果您必须在doInBackground()中执行此操作,请将其放在Runnable中,如代码中所示。

Runnable run = new Runnable() {

    @Override
    public void run() {
        Toast.makeText(getApplicationContext(), "WORKING !!!", LENGTH_LONG).show();

    }
}; MainActivity.this.runOnUiThread(run);

详细了解AsyncTasks here,特别是标题为 4个步骤

的部分

答案 1 :(得分:1)

您无法在非ui线程中显示Toast。

您可以将消息发布到UI线程,并让UI线程处理该消息。

答案 2 :(得分:1)

您不能在非UI线程中使用Toast。你可以从onPostExecute()中显示一个toast,因为它是从UI线程调用的,而不是来自doInBackground(),因为它在自己的线程中运行。

答案 3 :(得分:0)

不要尝试在后台线程中显示Toast

private class DownloadStuff extends AsyncTask<String, String, String>{

        protected String doInBackground(String... url) {
            // TODO Auto-generated method stub
            Log.i("CHECK", "OUTSIDE");
            try{
                // ....
                Toast.makeText(getApplicationContext(), "WORKING !!!", LENGTH_LONG).show();
            }catch(IOException i){

                Toast.makeText(getApplicationContext(), "ERROR: unable to establish contact with URL", LENGTH_LONG).show();     
            }
            return null;
}

答案 4 :(得分:0)

当您使用Async Task时,请确保它不能在主线程上运行,因此您无法显示Toast

AsyncTask类有五种方法

  • onPreExecute() - 此方法在后台处理之前在UI线程上运行 开始。
  • doInBackground() - 此方法在后台运行,并且是所有的方法 真正的工作已经完成。
  • publishProgress() - 此方法,来自doInBackground() 方法,定期通知UI线程有关后台进程的信息 进展。此方法将信息发送到UI进程。
  • onProgressUpdate() - 无论何时,此方法都在UI线程上运行 doInBackground()方法调用publishProgress()。这种方法收到 来自后台流程的信息。
  • onPostExecute() - 此方法在后台运行UI线程 处理完成。

因此,只要您想执行显示进程状态等操作,就应该使用OnProcessUpdate()方法,因为它允许您与主线程进行交互。