android.os.NetworkOnMainThreadException

使用android测试访问web服务器的webservice时,在MainActivity的主线程中访问webservice,代码如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.example.myandroidpro;  
  2.   
  3. import java.io.File;  
  4.   
  5. import org.ksoap2.SoapEnvelope;  
  6. import org.ksoap2.serialization.SoapObject;  
  7. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  8. import org.ksoap2.transport.HttpTransportSE;  
  9.   
  10. import android.annotation.SuppressLint;  
  11. import android.app.Activity;  
  12. import android.os.Bundle;  
  13. import android.os.Environment;  
  14. import android.os.StrictMode;  
  15. import android.view.View;  
  16. import android.view.View.OnClickListener;  
  17. import android.widget.Button;  
  18. import android.widget.Toast;  
  19.   
  20. public class MainActivity extends Activity {  
  21.   
  22.     private static String NAMESPACE = "http://service.cxf.test/";  
  23.     // webService地址  
  24.     private static String URL = "http://192.168.1.119:8080/CxfWebService/services/HelloService/";  
  25.   
  26.     private String method_name = null;  
  27.     private Button activity_main_btn1;  
  28.   
  29.     @SuppressLint("NewApi"@Override  
  30.     protected void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.activity_main);  
  33.         StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();  
  34.         StrictMode.setThreadPolicy(policy);  
  35.           
  36.         File rootDirectory = Environment.getRootDirectory();//获取手机根目录  
  37.         File storageDirectory = Environment.getExternalStorageDirectory();//获取SD卡根目录  
  38.   
  39.         for(File file : rootDirectory.listFiles()){  
  40.             System.err.println(file.isDirectory()+","+file.getName());  
  41.         }   
  42.           
  43.         findVIew();  
  44.           
  45.         activity_main_btn1.setOnClickListener(new OnClickListener() {  
  46.               
  47.             @Override  
  48.             public void onClick(View arg0) {  
  49.                 //发送webservice请求  
  50.                     sayHi("zxn");      
  51.             }  
  52.         });  
  53.           
  54.     }  
  55.   
  56.     private void findVIew() {  
  57.         activity_main_btn1 = (Button) findViewById(R.id.activity_main_btn1);  
  58.   
  59.     }  
  60.   
  61.     private String sayHi(String name) {  
  62.         String result = null;  
  63.         // (1) 指定webservice的命名空间和调用的方法名  
  64.         method_name = "sayHi";  
  65.         SoapObject soapObj = new SoapObject(NAMESPACE, method_name);  
  66.         /** 
  67.          * (2) 设置调用方法的参数值,如果没有参数,可以省略。 要注意的是,参数必须和服务声明的@WebParam里面的变量名对应 
  68.          */  
  69.         soapObj.addProperty("name", name);  
  70.         // (3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述  
  71.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(  
  72.                 SoapEnvelope.VER11);  
  73.         // envelope.bodyOut = rpc;  
  74.         envelope.dotNet = false;  
  75.         envelope.setOutputSoapObject(soapObj);  
  76.         // (4)创建HttpTransportsSE对象。通过AndroidHttpTransport类的构造方法可以指定WebService的WSDL文档的URL  
  77.         HttpTransportSE ht = new HttpTransportSE(URL);  
  78.         try {  
  79.             // (5)使用call方法调用WebService方法  
  80.             ht.call(null, envelope);  
  81.             // (6)使用getResponse方法获得WebService方法的返回结果  
  82.             if (envelope.getResponse() != null) {  
  83.                 System.out.println(envelope.getResponse());  
  84.                 result = String.valueOf(envelope.getResponse());  
  85.                 Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT)  
  86.                         .show();  
  87.             }  
  88.         } catch (Exception e) {  
  89.             e.printStackTrace();  
  90.         }  
  91.         return result;  
  92.     }  
  93.   
  94. }  

由于在主线程中访问网络,android版本为4.3,导致如下异常:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="background-color: rgb(255, 204, 255);">05-15 02:00:05.769: W/System.err(2269): android.os.NetworkOnMainThreadException  
  2. 05-15 02:00:05.799: W/System.err(2269):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1133)</span>  
  3. 05-15 02:00:05.799: W/System.err(2269):     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)  
  4. 05-15 02:00:05.810: W/System.err(2269):     at libcore.io.IoBridge.connectErrno(IoBridge.java:144)  
  5. 05-15 02:00:05.810: W/System.err(2269):     at libcore.io.IoBridge.connect(IoBridge.java:112)  
  6. 05-15 02:00:05.869: D/dalvikvm(2269): GC_FOR_ALLOC freed 345K, 14% free 2674K/3076K, paused 48ms, total 52ms  
  7. 05-15 02:00:05.869: W/System.err(2269):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)  
  8. 05-15 02:00:05.880: W/System.err(2269):     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)  
  9. 05-15 02:00:05.880: W/System.err(2269):     at java.net.Socket.connect(Socket.java:842)  
  10. 05-15 02:00:05.889: W/System.err(2269):     at libcore.net.http.HttpConnection.<init>(HttpConnection.java:76)  
  11. 05-15 02:00:05.889: W/System.err(2269):     at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)  
  12. 05-15 02:00:05.899: W/System.err(2269):     at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)  
  13. 05-15 02:00:05.899: W/System.err(2269):     at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)  
  14. 05-15 02:00:05.899: W/System.err(2269):     at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)  
  15. 05-15 02:00:05.899: W/System.err(2269):     at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)  
  16. 05-15 02:00:05.899: W/System.err(2269):     at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)  
  17. 05-15 02:00:05.909: W/System.err(2269):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)  
  18. 05-15 02:00:05.909: W/System.err(2269):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)  
  19. 05-15 02:00:05.909: W/System.err(2269):     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)  
  20. 05-15 02:00:05.909: W/System.err(2269):     at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197)  
  21. 05-15 02:00:05.919: W/System.err(2269):     at org.ksoap2.transport.ServiceConnectionSE.openOutputStream(ServiceConnectionSE.java:126)  
  22. 05-15 02:00:05.919: W/System.err(2269):     at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:185)  
  23. 05-15 02:00:05.929: W/System.err(2269):     at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:118)  
  24. 05-15 02:00:05.929: W/System.err(2269):     at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:113)  
  25. 05-15 02:00:05.969: W/System.err(2269):     at com.example.myandroidpro.MainActivity.sayHi(MainActivity.java:77)  
  26. 05-15 02:00:05.969: W/System.err(2269):     at com.example.myandroidpro.MainActivity.access$0(MainActivity.java:58)  
  27. 05-15 02:00:05.969: W/System.err(2269):     at com.example.myandroidpro.MainActivity$1.onClick(MainActivity.java:47)  
  28. 05-15 02:00:05.969: W/System.err(2269):     at android.view.View.performClick(View.java:4240)  
  29. 05-15 02:00:05.979: W/System.err(2269):     at android.view.View$PerformClick.run(View.java:17721)  
  30. 05-15 02:00:05.979: W/System.err(2269):     at android.os.Handler.handleCallback(Handler.java:730)  
  31. 05-15 02:00:06.012: W/System.err(2269):     at android.os.Handler.dispatchMessage(Handler.java:92)  
  32. 05-15 02:00:06.012: W/System.err(2269):     at android.os.Looper.loop(Looper.java:137)  
  33. 05-15 02:00:06.019: W/System.err(2269):     at android.app.ActivityThread.main(ActivityThread.java:5103)  
  34. 05-15 02:00:06.019: W/System.err(2269):     at java.lang.reflect.Method.invokeNative(Native Method)  
  35. 05-15 02:00:06.019: W/System.err(2269):     at java.lang.reflect.Method.invoke(Method.java:525)  
  36. 05-15 02:00:06.034: W/System.err(2269):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)  
  37. 05-15 02:00:06.034: W/System.err(2269):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)  
  38. 05-15 02:00:06.039: W/System.err(2269):     at dalvik.system.NativeStart.main(Native Method)  

原因:

android.os.NetworkOnMainThreadException是说不要在主线程中访问网络,这个是android3.0版本开始就强制程序不能在主线程中访问网络,要把访问网络放在独立的线程中。

解决:

在开发中,为了防止访问网络阻塞主线程,一般都要把访问网络放在独立线程中或者异步线程AsyncTask中。

 先在AndroidManifest.xml文件manifest节点中添加如下配置:

[java]  view plain copy
  1. <uses-permission android:name="android.permission.INTERNET"/>  

1、想要忽略这些强制策略问题的话,可以在onCreate()方法里面加上

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();  
  2. StrictMode.setThreadPolicy(policy);  
并在方法上加上@SuppressLint("NewApi"),重试,OK。


2、将网络访问放到单独线程中:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.example.myandroidpro;  
  2.   
  3. import java.io.File;  
  4.   
  5. import org.ksoap2.SoapEnvelope;  
  6. import org.ksoap2.serialization.SoapObject;  
  7. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  8. import org.ksoap2.transport.HttpTransportSE;  
  9.   
  10. import android.annotation.SuppressLint;  
  11. import android.app.Activity;  
  12. import android.os.Bundle;  
  13. import android.os.Environment;  
  14. import android.os.Handler;  
  15. import android.os.Looper;  
  16. import android.os.Message;  
  17. import android.os.StrictMode;  
  18. import android.view.View;  
  19. import android.view.View.OnClickListener;  
  20. import android.widget.Button;  
  21. import android.widget.Toast;  
  22.   
  23. public class MainActivity extends Activity {  
  24.   
  25.     private static String NAMESPACE = "http://service.cxf.test/";  
  26.     // webService地址  
  27.     private static String URL = "http://192.168.1.119:8080/CxfWebService/services/HelloService/";  
  28.   
  29.     private String method_name = null;  
  30.     private Button activity_main_btn1;  
  31.   
  32.     private int ANDROID_ACCESS_CXF_WEBSERVICES = 001;   
  33.       
  34.       
  35.     private Handler handler = new Handler(){  
  36.         @Override  
  37.         public void handleMessage(Message msg) {  
  38.             String result = (String) msg.getData().get("result");  
  39.             String obj = (String) msg.obj;//  
  40.             activity_main_btn1.setText("请求结果为:"+result);  
  41.         }  
  42.           
  43.     };  
  44.       
  45.     protected void onCreate(Bundle savedInstanceState) {  
  46.         super.onCreate(savedInstanceState);  
  47.         setContentView(R.layout.activity_main);  
  48.           
  49.         File rootDirectory = Environment.getRootDirectory();//获取手机根目录  
  50.         File storageDirectory = Environment.getExternalStorageDirectory();//获取SD卡根目录  
  51.   
  52.         for(File file : rootDirectory.listFiles()){  
  53.             System.err.println(file.isDirectory()+","+file.getName());  
  54.         }   
  55.           
  56.         findVIew();  
  57.           
  58.         activity_main_btn1.setOnClickListener(new OnClickListener() {  
  59.             @Override  
  60.             public void onClick(View view) {  
  61.                 Thread accessWebServiceThread = new Thread(new WebServiceHandler());  
  62.                 accessWebServiceThread.start();  
  63.                   
  64.             }  
  65.         });  
  66.           
  67.     }  
  68.   
  69.     class WebServiceHandler implements Runnable{  
  70.         @Override  
  71.         public void run() {  
  72.             Looper.prepare();  
  73.             String result = sayHi("zxn");  
  74.             Message message = new Message();  
  75.             Bundle bundle = new Bundle();  
  76.             bundle.putString("result", result);  
  77.             message.what = ANDROID_ACCESS_CXF_WEBSERVICES;//设置消息标示  
  78.             message.obj = "zxn";  
  79.             message. setData(bundle);//消息内容  
  80.             handler.sendMessage(message);//发送消息  
  81.             Looper.loop();  
  82.         }  
  83.           
  84.     }  
  85.       
  86.     private void findVIew() {  
  87.         activity_main_btn1 = (Button) findViewById(R.id.activity_main_btn1);  
  88.   
  89.     }  
  90.   
  91.     private String sayHi(String name) {  
  92.         String result = null;  
  93.         // (1) 指定webservice的命名空间和调用的方法名  
  94.         method_name = "sayHi";  
  95.         SoapObject soapObj = new SoapObject(NAMESPACE, method_name);  
  96.         /** 
  97.          * (2) 设置调用方法的参数值,如果没有参数,可以省略。 要注意的是,参数必须和服务声明的@WebParam里面的变量名对应 
  98.          */  
  99.         soapObj.addProperty("name", name);  
  100.         // (3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述  
  101.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(  
  102.                 SoapEnvelope.VER11);  
  103.         // envelope.bodyOut = rpc;  
  104.         envelope.dotNet = false;  
  105.         envelope.setOutputSoapObject(soapObj);  
  106.         // (4)创建HttpTransportsSE对象。通过AndroidHttpTransport类的构造方法可以指定WebService的WSDL文档的URL  
  107.         HttpTransportSE ht = new HttpTransportSE(URL);  
  108.         try {  
  109.             // (5)使用call方法调用WebService方法  
  110.             ht.call(null, envelope);  
  111.             // (6)使用getResponse方法获得WebService方法的返回结果  
  112.             if (envelope.getResponse() != null) {  
  113.                 System.out.println(envelope.getResponse());  
  114.                 result = String.valueOf(envelope.getResponse());  
  115.                 Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT)  
  116.                         .show();  
  117.             }  
  118.         } catch (Exception e) {  
  119.             e.printStackTrace();  
  120.         }  
  121.         return result;  
  122.     }  
  123.   
  124. }  

MainActivity的相应布局如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context=".MainActivity" >  
  10.   
  11.     <LinearLayout android:layout_width="fill_parent"  
  12.         android:layout_height="fill_parent"  
  13.         android:orientation="vertical">  
  14.         <TextView  
  15.             android:id="@+id/activity_main_tv1"  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="wrap_content"  
  18.             android:text="@string/hello_world" />  
  19.   
  20.         <Button  
  21.             android:id="@+id/activity_main_btn1"  
  22.             android:layout_width="match_parent"  
  23.             android:layout_height="wrap_content"  
  24.             android:text="@string/test_for_cxf_webservice" />  
  25.     </LinearLayout>  
  26. </RelativeLayout>  

3、将网络访问放到异步任务AsyncTask中,代码如下:

[java]  view plain copy
  1. package com.example.myandroidpro;  
  2.   
  3. import java.io.File;  
  4.   
  5. import org.ksoap2.SoapEnvelope;  
  6. import org.ksoap2.serialization.SoapObject;  
  7. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  8. import org.ksoap2.transport.HttpTransportSE;  
  9.   
  10. import android.app.Activity;  
  11. import android.os.AsyncTask;  
  12. import android.os.Bundle;  
  13. import android.os.Environment;  
  14. import android.view.View;  
  15. import android.view.View.OnClickListener;  
  16. import android.widget.Button;  
  17.   
  18. public class MainActivity extends Activity {  
  19.   
  20.     private static String NAMESPACE = "http://service.cxf.test/";  
  21.     // webService地址  
  22.     private static String URL = "http://192.168.1.119:8080/CxfWebService/services/HelloService/";  
  23.   
  24.     private String method_name = null;  
  25.     private Button activity_main_btn1;  
  26.   
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.activity_main);  
  30.           
  31.         File rootDirectory = Environment.getRootDirectory();//获取手机根目录  
  32.         File storageDirectory = Environment.getExternalStorageDirectory();//获取SD卡根目录  
  33.   
  34.         for(File file : rootDirectory.listFiles()){  
  35.             System.err.println(file.isDirectory()+","+file.getName());  
  36.         }   
  37.           
  38.         findVIew();  
  39.           
  40.         activity_main_btn1.setOnClickListener(new OnClickListener() {  
  41.             @Override  
  42.             public void onClick(View view) {  
  43.                 accessWSAction();  
  44.             }  
  45.   
  46.             private void accessWSAction() {  
  47.                 new AsyncTask<String, Void, Object>() {  
  48.                       
  49.                     //在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,  
  50.                     // 后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户.  
  51.                     protected void onPostExecute(Object result) {  
  52.                         super.onPostExecute(result);  
  53.                         activity_main_btn1.setText("请求结果为:"+result);//可以更新UI  
  54.                     }  
  55.   
  56.                     //该方法运行在后台线程中,因此不能在该线程中更新UI,UI线程为主线程  
  57.                     protected Object doInBackground(String... params) {  
  58.                         String result = sayHi("zxn");  
  59. //                      activity_main_btn1.setText("请求结果为:"+result);  
  60.                         return result;  
  61.                     }  
  62.   
  63.                 }.execute();  
  64.                   
  65.             }  
  66.         });  
  67.     }  
  68.   
  69.     private void findVIew() {  
  70.         activity_main_btn1 = (Button) findViewById(R.id.activity_main_btn1);  
  71.   
  72.     }  
  73.   
  74.     private String sayHi(String name) {  
  75.         String result = null;  
  76.         // (1) 指定webservice的命名空间和调用的方法名  
  77.         method_name = "sayHi";  
  78.         SoapObject soapObj = new SoapObject(NAMESPACE, method_name);  
  79.         /** 
  80.          * (2) 设置调用方法的参数值,如果没有参数,可以省略。 要注意的是,参数必须和服务声明的@WebParam里面的变量名对应 
  81.          */  
  82.         soapObj.addProperty("name", name);  
  83.         // (3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述  
  84.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(  
  85.                 SoapEnvelope.VER11);  
  86.         // envelope.bodyOut = rpc;  
  87.         envelope.dotNet = false;  
  88.         envelope.setOutputSoapObject(soapObj);  
  89.         // (4)创建HttpTransportsSE对象。通过AndroidHttpTransport类的构造方法可以指定WebService的WSDL文档的URL  
  90.         HttpTransportSE ht = new HttpTransportSE(URL);  
  91.         try {  
  92.             // (5)使用call方法调用WebService方法  
  93.             ht.call(null, envelope);  
  94.             // (6)使用getResponse方法获得WebService方法的返回结果  
  95.             if (envelope.getResponse() != null) {  
  96.                 System.out.println(envelope.getResponse());  
  97.                 result = String.valueOf(envelope.getResponse());  
  98. //              Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT)  
  99. //                      .show();  
  100.             }  
  101.         } catch (Exception e) {  
  102.             e.printStackTrace();  
  103.         }  
  104.         return result;  
  105.     }  
  106.   
  107. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值