Android异步任务如何与UrlConnection一起使用

时间:2015-09-25 10:13:58

标签: android android-asynctask

我是android的新手。我正在开发一个应用程序,它将从文件中的目标URL加载内容。如果网址不起作用,它将联系我们的服务器以请求正确的网址。如果仍然失败,那么它将从用户输入对话框中询问URL。它会尝试再次初始化。我有这样的代码:

    if (initialize(target)!=true) {
        JSONObject jsonParam = new JSONObject();
        try {
            jsonParam.put("sns", getSerial(PREF_NAME));
            jsonParam.put("code", pwd);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        target = getContent(samURL + "/sam_ip", jsonParam);
        if (initialize(target)!=true) {
            askIpUserDialog();
        }
    }

和initialize()如下

private boolean initialize(String url) {
    Boolean success = false;
    if ((!url.trim().startsWith("http://")) && (!url.trim().startsWith("https://"))) {
        url = "http://" + url;
    }
    if (url.endsWith("/")) {
        url = url.substring(0,url.length()-1);
    }
    String sUrl = url + "/android_view";

    URL pUrl;
    HttpURLConnection urlConn = null;
    try {
        DataOutputStream printout;
        DataInputStream input;
        pUrl = new URL (sUrl);
        urlConn = (HttpURLConnection) pUrl.openConnection();
        urlConn.setDoInput (true);
        urlConn.setDoOutput (true);
        urlConn.setUseCaches (false);
        urlConn.setRequestProperty("Content-Type","application/json");
        urlConn.setRequestProperty("Host", "android.schoolportal.gr");
        urlConn.connect();

        //Create JSONObject here
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("snc", serialClient);
        jsonParam.put("code", pwd);

        printout = new DataOutputStream(urlConn.getOutputStream());
        String str = jsonParam.toString();
        byte[] data = str.getBytes("UTF-8");
        printout.write(data);
        printout.flush();
        printout.close ();

        int HttpResult = urlConn.getResponseCode();
        if(HttpResult == HttpURLConnection.HTTP_OK){
            success = true;
            WebView view=(WebView) this.findViewById(R.id.webView);
            view.setWebChromeClient(new WebChromeClient());
            view.setWebViewClient(new WebViewClient());
            view.getSettings().setJavaScriptEnabled(true);
            view.loadUrl(sUrl);
        }else{
            success = false;
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    } finally{
        if(urlConn!=null)
            urlConn.disconnect();
    }
    return success;
}

我只知道在android中,url连接应该在单独的线程中运行。这就是我收到以下错误的原因:

 Caused by: android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork

我的问题是,如何使用AsyncTask来避免错误? 我看到有doInBackground(),我可以在那里放置initialize()函数。 我也看到有onPostExecute()事件,我可以检查doInBackground()的结果,但是我还不明白如何检索放在doInBackground()里面的initialize()的返回?

奖金问题,稍后我想把所有这些工作都放在一个意向服务中。我是否需要使用asynctask? intentservice本身是一个asynctask吗?

2 个答案:

答案 0 :(得分:0)

你可以尝试这样的事情,也可以使用不同的线程

   final Handler h = new Handler();
    Runnable r = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            final File file  = new File(path);
            Log.i("path",path);
            downloadFile(url[j], file);
            h.post(new Runnable(){

                @Override
                public void run() {

                txt.setText(""+jp);
                jp++;

                }

            });
            }

        }
    };
    new Thread(r).start();

}

private static void downloadFile(String url, File outputFile) {
      try {
          URL u = new URL(url);
          URLConnection conn = u.openConnection();
          int contentLength = conn.getContentLength();
          Log.i("len","" + contentLength);
          Log.i("url1","Streaming from "+url+ "...."); 
          DataInputStream stream = new DataInputStream(u.openStream());

            byte[] buffer = new byte[contentLength];
            stream.readFully(buffer);
            stream.close();

            DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
            fos.write(buffer);
            fos.flush();
            fos.close();
      } catch(FileNotFoundException e) {
          Log.v("FileError" , e.toString());
          return; // swallow a 404
      } catch (IOException e) {
          Log.v("FileError" , e.toString());
          return; // swallow a 404
      }
      catch (Exception e) {
          Log.v("FileError" , e.toString());
          return; // swallow a 404
      }
    }

并且您也无法访问不同线程上的ui元素,您必须使用处理程序或在ui线程上运行。

@Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    try{   
        this.pd = ProgressDialog.show(this, "Loading..", "Please Wait...", true, false);
        new AsyncAction().execute();

    }catch (Exception e) {
        e.printStackTrace();
    }
}

private class AsyncAction extends AsyncTask<String, Void, String> {
    protected Void doInBackground(String... args) { 
          //do your stuff here        }
} 

}

答案 1 :(得分:0)

网络流量(以及需要一些时间来处理的所有其他逻辑)应始终由后台线程处理,而不应在主线程上处理。

使用ASyncTask执行逻辑。

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

    @Override
    protected String doInBackground(String... params) {
       // perform your network logic here
        return "YourResult";
    }

    @Override
    protected void onPostExecute(String result) {
        // Update your screen with the results.
    }
}

在代码中调用ASyncTask:

new YourTask().execute("");