在Android 4.1中调用Web服务

时间:2012-08-24 12:54:08

标签: android android-asynctask

我这里的代码在2.3中一直有效,现在我们必须更新它,我收到很多错误,比如NetworkOnMainThreadException。我想从我的Web服务中获取一个xml,将其关闭并将其解析为数组列表。这是代码

//Gets the xml from the url specified
String CallWebService(String url){
        String xml = null;
        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);

            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            xml = EntityUtils.toString(httpEntity);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // return XML
        return xml;
}
//Parses the xml to get DOM element 
public Document GetDomElement(String xml){
    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        DocumentBuilder db = dbf.newDocumentBuilder();

        InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is); 

        } catch (ParserConfigurationException e) {
            //Log.e("Error: ", e.getMessage());
            return null;
        } catch (SAXException e) {
            //Log.e("Error: ", e.getMessage());
            return null;
        } catch (IOException e) {
            //Log.e("Error: ", e.getMessage());
            return null;
        }
            // return DOM
        return doc;
}
//Gets the child nodes of the xml
public String getValue(Element item, String str) {
    NodeList n = item.getElementsByTagName(str);
    return this.getElementValue(n.item(0));
}

public final String getElementValue( Node elem ) {
         Node child;
         if( elem != null){
             if (elem.hasChildNodes()){
                 for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                     if(child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE){
                         return child.getNodeValue();
                     }
                 }
             }
         }
         return "";
 }

我也有getChildElements方法。问题是我打电话给这个方法。我曾经这样做过:

String serviceURL = "http://webservice.example.com/";
String xml = CallWebService(serviceURL);
Document doc = GetDomElement(xml); // getting DOM element

NodeList nl = doc.getElementsByTagName("details");
getChildElements(nl); 

但现在在4.1中我需要异步执行此操作而我不知道如何执行此操作。任何帮助将不胜感激。

修改

这就是我所拥有的线程无法启动

final String serviceURL = "urlString";
mHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {                             
     if(msg.what == JOB_COMPLETE) {
       String xml = (String) msg.obj;
       Document doc = GetDomElement(xml); // getting DOM element

       NodeList nl = doc.getElementsByTagName("details");
       getChildElements(nl); 
    }
    super.handleMessage(msg);
  }
};

Thread t = new Thread() {
    @Override
    public void run() {
       String xml = CallWebService(serviceURL);
       Message msg = Message.obtain(mHandler, JOB_COMPLETE, xml);
       msg.sendToTarget();
  }
};                                              
t.start();

修改

所以我尝试异步方式,它仍然无法正常工作。它根本没有击中GetDomElement。这是代码。

   //I call this in my onCreate()
   new getAppInfo().execute("http://webservice.example.com");

   private class getAppInfo extends AsyncTask<String, Void, String> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected String doInBackground(String... urls) {
        return CallWebService(urls[0]);
    }

    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(String xml) {
        Document doc = GetDomElement(xml); // getting DOM element

        NodeList nl = doc.getElementsByTagName("details");
        getChildElements(nl); 
    }
}

4 个答案:

答案 0 :(得分:0)

您必须实现AsyncTask:

http://developer.android.com/reference/android/os/AsyncTask.html

顺便说一下,这需要Android 3(如果我记得的话)。

我已在我的应用中实现了此功能,您可以在此处浏览我的代码:https://github.com/enrichman/roma-tre/blob/master/src/com/roma3/infovideo/utility/rss/RssTask.java

答案 1 :(得分:0)

答案 2 :(得分:0)

在活动onCreate中的主ui线程中定义一个处理程序,例如

private Handler mHandler;
private static int JOB_COMPLETE = 1;   

mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if(msg.what == JOB_COMPLETE) {
            String xml = (String) msg.obj;
            // do whatever you want with that string
        }
        super.handleMessage(msg);
    }
 };

然后在后台线程中运行所有长期工作

final String url = "...........";
Thread t = new Thread() {
    @Override
    public void run() {
        String xml = CallWebService(url);
        Message msg = Message.obtain(mHandler, JOB_COMPLETE, xml);
        msg.sendToTarget();
    }
};
t.start();

答案 3 :(得分:0)

当应用程序尝试在其主线程上执行网络操作时引发的异常。

仅针对Honeycomb SDK或更高版本的应用程序进行此操作。针对早期SDK版本的应用程序可以在其主要事件循环线程上进行网络连接,但是非常不鼓励这样做 see android developers page

使用异步任务执行与网络相关的任务或尝试使用安全线程