android之android.os.NetworkOnMainThreadException异常 使用android测试访问web服务器的webservice时,在MainActivity的主线程中访问webservice,代码如下: package com.example.myandroidpro;
import java.io.File;
import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE;
import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.StrictMode; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast;
public class MainActivity extends Activity {
    private static String NAMESPACE = "http://service.cxf.test/";     // webService地址     private static String URL = "http://192.168.1.119:8080/CxfWebService/services/HelloService/";
    private String method_name = null;     private Button activity_main_btn1;
    @SuppressLint("NewApi") @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();         StrictMode.setThreadPolicy(policy);                  File rootDirectory = Environment.getRootDirectory();//获取手机根目录         File storageDirectory = Environment.getExternalStorageDirectory();//获取SD卡根目录
        for(File file : rootDirectory.listFiles()){             System.err.println(file.isDirectory()+","+file.getName());         }                   findVIew();                  activity_main_btn1.setOnClickListener(new OnClickListener() {                          @Override             public void onClick(View arg0) {                 //发送webservice请求                     sayHi("zxn");                 }         });              }
    private void findVIew() {         activity_main_btn1 = (Button) findViewById(R.id.activity_main_btn1);
    }
    private String sayHi(String name) {         String result = null;         // (1) 指定webservice的命名空间和调用的方法名         method_name = "sayHi";         SoapObject soapObj = new SoapObject(NAMESPACE, method_name);         /**          * (2) 设置调用方法的参数值,如果没有参数,可以省略。 要注意的是,参数必须和服务声明的@WebParam里面的变量名对应          */         soapObj.addProperty("name", name);         // (3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(                 SoapEnvelope.VER11);         // envelope.bodyOut = rpc;         envelope.dotNet = false;         envelope.setOutputSoapObject(soapObj);         // (4)创建HttpTransportsSE对象。通过AndroidHttpTransport类的构造方法可以指定WebService的WSDL文档的URL         HttpTransportSE ht = new HttpTransportSE(URL);         try {             // (5)使用call方法调用WebService方法             ht.call(null, envelope);             // (6)使用getResponse方法获得WebService方法的返回结果             if (envelope.getResponse() != null) {                 System.out.println(envelope.getResponse());                 result = String.valueOf(envelope.getResponse());                 Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT)                         .show();             }         } catch (Exception e) {             e.printStackTrace();         }         return result;     }
}
由于在主线程中访问网络,android版本为4.3,导致如下异常: 05-15 02:00:05.769: W/System.err(2269): android.os.NetworkOnMainThreadException 05-15 02:00:05.799: W/System.err(2269):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1133) 05-15 02:00:05.799: W/System.err(2269):  at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84) 05-15 02:00:05.810: W/System.err(2269):  at libcore.io.IoBridge.connectErrno(IoBridge.java:144) 05-15 02:00:05.810: W/System.err(2269):  at libcore.io.IoBridge.connect(IoBridge.java:112) 05-15 02:00:05.869: D/dalvikvm(2269): GC_FOR_ALLOC freed 345K, 14% free 2674K/3076K, paused 48ms, total 52ms 05-15 02:00:05.869: W/System.err(2269):  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192) 05-15 02:00:05.880: W/System.err(2269):  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459) 05-15 02:00:05.880: W/System.err(2269):  at java.net.Socket.connect(Socket.java:842) 05-15 02:00:05.889: W/System.err(2269):  at libcore.net.http.HttpConnection.(HttpConnection.java:76) 05-15 02:00:05.889: W/System.err(2269):  at libcore.net.http.HttpConnection.(HttpConnection.java:50) 05-15 02:00:05.899: W/System.err(2269):  at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340) 05-15 02:00:05.899: W/System.err(2269):  at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87) 05-15 02:00:05.899: W/System.err(2269):  at libcore.net.http.HttpConnection.connect(HttpConnection.java:128) 05-15 02:00:05.899: W/System.err(2269):  at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316) 05-15 02:00:05.899: W/System.err(2269):  at libcore.net.http.HttpEngine.connect(HttpEngine.java:311) 05-15 02:00:05.909: W/System.err(2269):  at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290) 05-15 02:00:05.909: W/System.err(2269):  at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240) 05-15 02:00:05.909: W/System.err(2269):  at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81) 05-15 02:00:05.909: W/System.err(2269):  at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197) 05-15 02:00:05.919: W/System.err(2269):  at org.ksoap2.transport.ServiceConnectionSE.openOutputStream(ServiceConnectionSE.java:126) 05-15 02:00:05.919: W/System.err(2269):  at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:185) 05-15 02:00:05.929: W/System.err(2269):  at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:118) 05-15 02:00:05.929: W/System.err(2269):  at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:113) 05-15 02:00:05.969: W/System.err(2269):  at com.example.myandroidpro.MainActivity.sayHi(MainActivity.java:77) 05-15 02:00:05.969: W/System.err(2269):  at com.example.myandroidpro.MainActivity.access$0(MainActivity.java:58) 05-15 02:00:05.969: W/System.err(2269):  at com.example.myandroidpro.MainActivity$1.onClick(MainActivity.java:47) 05-15 02:00:05.969: W/System.err(2269):  at android.view.View.performClick(View.java:4240) 05-15 02:00:05.979: W/System.err(2269):  at android.view.View$PerformClick.run(View.java:17721) 05-15 02:00:05.979: W/System.err(2269):  at android.os.Handler.handleCallback(Handler.java:730) 05-15 02:00:06.012: W/System.err(2269):  at android.os.Handler.dispatchMessage(Handler.java:92) 05-15 02:00:06.012: W/System.err(2269):  at android.os.Looper.loop(Looper.java:137) 05-15 02:00:06.019: W/System.err(2269):  at android.app.ActivityThread.main(ActivityThread.java:5103) 05-15 02:00:06.019: W/System.err(2269):  at java.lang.reflect.Method.invokeNative(Native Method) 05-15 02:00:06.019: W/System.err(2269):  at java.lang.reflect.Method.invoke(Method.java:525) 05-15 02:00:06.034: W/System.err(2269):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 05-15 02:00:06.034: W/System.err(2269):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 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节点中添加如下配置:
1、想要忽略这些强制策略问题的话,可以在onCreate()方法里面加上 StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); 并在方法上加上@SuppressLint("NewApi"),重试,OK。
2、将网络访问放到单独线程中: package com.example.myandroidpro;
import java.io.File;
import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE;
import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.StrictMode; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast;
public class MainActivity extends Activity {
private static String NAMESPACE = "http://service.cxf.test/"; // webService地址 private static String URL = "http://192.168.1.119:8080/CxfWebService/services/HelloService/";
private String method_name = null; private Button activity_main_btn1;
private int ANDROID_ACCESS_CXF_WEBSERVICES = 001;  private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { String result = (String) msg.getData().get("result"); String obj = (String) msg.obj;// activity_main_btn1.setText("请求结果为:"+result); } };     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);                  File rootDirectory = Environment.getRootDirectory();//获取手机根目录         File storageDirectory = Environment.getExternalStorageDirectory();//获取SD卡根目录
        for(File file : rootDirectory.listFiles()){          System.err.println(file.isDirectory()+","+file.getName());         }                   findVIew();                  activity_main_btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { Thread accessWebServiceThread = new Thread(new WebServiceHandler()); accessWebServiceThread.start(); } });              }
    class WebServiceHandler implements Runnable{ @Override public void run() { Looper.prepare(); String result = sayHi("zxn"); Message message = new Message(); Bundle bundle = new Bundle(); bundle.putString("result", result); message.what = ANDROID_ACCESS_CXF_WEBSERVICES;//设置消息标示 message.obj = "zxn"; message. setData(bundle);//消息内容 handler.sendMessage(message);//发送消息 Looper.loop(); }          }      private void findVIew() { activity_main_btn1 = (Button) findViewById(R.id.activity_main_btn1);
}
private String sayHi(String name) { String result = null; // (1) 指定webservice的命名空间和调用的方法名 method_name = "sayHi"; SoapObject soapObj = new SoapObject(NAMESPACE, method_name); /**  * (2) 设置调用方法的参数值,如果没有参数,可以省略。 要注意的是,参数必须和服务声明的@WebParam里面的变量名对应  */ soapObj.addProperty("name", name); // (3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); // envelope.bodyOut = rpc; envelope.dotNet = false; envelope.setOutputSoapObject(soapObj); // (4)创建HttpTransportsSE对象。通过AndroidHttpTransport类的构造方法可以指定WebService的WSDL文档的URL HttpTransportSE ht = new HttpTransportSE(URL); try { // (5)使用call方法调用WebService方法 ht.call(null, envelope); // (6)使用getResponse方法获得WebService方法的返回结果 if (envelope.getResponse() != null) { System.out.println(envelope.getResponse()); result = String.valueOf(envelope.getResponse()); Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT) .show(); } } catch (Exception e) { e.printStackTrace(); } return result; }
} MainActivity的相应布局如下:     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     tools:context=".MainActivity" >
            android:layout_height="fill_parent"         android:orientation="vertical">                     android:id="@+id/activity_main_tv1"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:text="@string/hello_world" />
                    android:id="@+id/activity_main_btn1"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:text="@string/test_for_cxf_webservice" />    
3、将网络访问放到异步任务AsyncTask中,代码如下: package com.example.myandroidpro;
import java.io.File;
import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;
public class MainActivity extends Activity {
private static String NAMESPACE = "http://service.cxf.test/"; // webService地址 private static String URL = "http://192.168.1.119:8080/CxfWebService/services/HelloService/";
private String method_name = null; private Button activity_main_btn1;
    protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);                  File rootDirectory = Environment.getRootDirectory();//获取手机根目录         File storageDirectory = Environment.getExternalStorageDirectory();//获取SD卡根目录
        for(File file : rootDirectory.listFiles()){          System.err.println(file.isDirectory()+","+file.getName());         }                   findVIew();                  activity_main_btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { accessWSAction(); }
private void accessWSAction() { new AsyncTask() { //在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用, // 后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户. protected void onPostExecute(Object result) { super.onPostExecute(result); activity_main_btn1.setText("请求结果为:"+result);//可以更新UI }
//该方法运行在后台线程中,因此不能在该线程中更新UI,UI线程为主线程 protected Object doInBackground(String... params) { String result = sayHi("zxn"); // activity_main_btn1.setText("请求结果为:"+result); return result; }
}.execute(); } });     }
private void findVIew() { activity_main_btn1 = (Button) findViewById(R.id.activity_main_btn1);
}
private String sayHi(String name) { String result = null; // (1) 指定webservice的命名空间和调用的方法名 method_name = "sayHi"; SoapObject soapObj = new SoapObject(NAMESPACE, method_name); /**  * (2) 设置调用方法的参数值,如果没有参数,可以省略。 要注意的是,参数必须和服务声明的@WebParam里面的变量名对应  */ soapObj.addProperty("name", name); // (3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); // envelope.bodyOut = rpc; envelope.dotNet = false; envelope.setOutputSoapObject(soapObj); // (4)创建HttpTransportsSE对象。通过AndroidHttpTransport类的构造方法可以指定WebService的WSDL文档的URL HttpTransportSE ht = new HttpTransportSE(URL); try { // (5)使用call方法调用WebService方法 ht.call(null, envelope); // (6)使用getResponse方法获得WebService方法的返回结果 if (envelope.getResponse() != null) { System.out.println(envelope.getResponse()); result = String.valueOf(envelope.getResponse()); // Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT) // .show(); } } catch (Exception e) { e.printStackTrace(); } return result; }
}

更多相关文章

  1. Android进程与线程基本知识四
  2. 全志A64 Android7.1屏蔽使用按键进入安全模式的方法
  3. Android使用AttributeSet自定义控件的方法
  4. 让Android不播放关机动画,而是显示一个关机进度条的方法
  5. android下拉菜单spinner的使用方法
  6. Android第五期 - 更新自己的apk本地与网络两种方法
  7. Android HandlerThread使用方法
  8. android利用Handler开启线程和关闭线程
  9. android-2.2以下杀进程方法:restartPackage();

随机推荐

  1. Android(安卓)Scroll
  2. Android(安卓)-- SurfaceFlinger 合成主
  3. Android开发指南中文版(二)Application Fun
  4. Android(安卓)视觉规范
  5. Android 编译C模块
  6. React Native Linking与 Android原生页面
  7. Flutter学习笔记(30)--Android原生与Flutte
  8. 在Android 开发中使用Protobuf的实践和经
  9. Android根据Button状态(normal,focused,p
  10. video for linux 编程的资料