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,导致如下异常:

<span style="background-color: rgb(255, 204, 255);">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)</span>
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.<init>(HttpConnection.java:76)
05-15 02:00:05.889: W/System.err(2269): 	at libcore.net.http.HttpConnection.<init>(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节点中添加如下配置:
<uses-permission android:name="android.permission.INTERNET"/>

  1. 想要忽略这些强制策略问题的话,可以在onCreate()方法里面加上
    @SuppressLint("NewApi")
    StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
    
  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的相应布局如下:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        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" >
     
        <LinearLayout android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">
            <TextView
                android:id="@+id/activity_main_tv1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />
     
            <Button
                android:id="@+id/activity_main_btn1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/test_for_cxf_webservice" />
        </LinearLayout>
    </RelativeLayout>
    
  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<String, Void, Object>() {
    					
    					//在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;
    	}
     
    }
    

原文链接:https://blog.csdn.net/zxnlmj/article/details/25887447

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值