调用Web服务时网络主线程异常

时间:2015-11-25 09:17:42

标签: java android web-services android-studio

我有这个java类:

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity
{
private static final String SOAP_ACTION = "http://tempuri.org/findContact";

private static final String OPERATION_NAME = "findContact";// your webservice web method name

private static final String WSDL_TARGET_NAMESPACE = "http://tempuri.org/";

private static final String SOAP_ADDRESS = "http://10.0.2.2:20959/test/Service.asmx";


TextView tvData1;
EditText edata;
Button button;
String studentNo;

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tvData1 = (TextView)findViewById(R.id.textView);

    button=(Button)findViewById(R.id.button);

    button.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

            SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE,     OPERATION_NAME);
            PropertyInfo propertyInfo = new PropertyInfo();
            propertyInfo.type = PropertyInfo.STRING_CLASS;
            propertyInfo.name = "eid";

            edata =(EditText)findViewById(R.id.editText);
            studentNo=edata.getText().toString();

            request.addProperty(propertyInfo, studentNo);

            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;

            envelope.setOutputSoapObject(request);

            HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS);

            try  {
                httpTransport.call(SOAP_ACTION, envelope);
                Object response = envelope.getResponse();
                tvData1.setText(response.toString());
            }  catch (Exception exception)   {
                tvData1.setText(exception.toString()+"  Or enter number is not Available!");
            }

            tvData1 = (TextView)findViewById(R.id.textView);

        }
    });


}

}

调用我在C#中创建的Web服务。我正在使用Android Studio创建一个调用此Web服务的应用程序。

但是当我运行它时我得到了这个错误:

android.os.NetworkOnMainThreadException

BTW我在清单中添加了互联网许可。

如何解决这个问题?

3 个答案:

答案 0 :(得分:0)

你必须制作asyncTask

public class MainActivity extends Activity{
...
....
 class CallWeb extends AsyncTask<String , String , String>{

    @Override
    protected String doInBackground(String... params) {

        HttpTransportSE httpTransport = new  HttpTransportSE(SOAP_ADDRESS);

        try  {
            httpTransport.call(SOAP_ACTION, envelope);
            Object response = envelope.getResponse();
            tvData1.setText(response.toString());
        }  catch (Exception exception)   {
            tvData1.setText(exception.toString()+"  Or enter number is not Available!");
        }

        return null;
    }
    }

我只是给你基本的想法,你必须自己设置,你需要了解这个错误。请同时浏览此链接。

AsyncTask Example

AsyncTask

Network in mainthread

答案 1 :(得分:0)

定位Honeycomb SDK或更高的应用程序将抛出Networkonmainthreadexception。允许早期版本在此主线程上进行联网但不鼓励(see ‘Keeping Your App Responsive’)。基本上这是由UI thread请求网络访问引起的,这会因为这些通常很昂贵的操作而破坏用户体验。

相反,这些操作需要在worker thread上进行,为此,您需要使用某种线程或处理程序。最常见的是AsyncTask

请参阅http://developer.android.com/reference/android/os/AsyncTask.html android记录了这个用法,但它基本归结为以下实现:

扩展AsyncTask的私有子类,实现以下方法:

  1. onPreExecute - 在执行任务之前在UI线程上调用并用于设置填充(例如显示进度条)

  2. doInBackground - 您想要执行的实际操作在onPreExecute之后立即触发

  3. onPostExecute - 在doInBackground完成后在UI线程上调用。这会将doInBackground的结果作为参数接收,然后可以在UI线程上使用。

  4. AsyncTask用于UI线程上不允许的操作,例如:

    • 打开套接字连接
    • HTTP请求(例如HTTPClient和HTTPURLConnection)
    • 尝试连接远程MySQL数据库
    • 下载文件

    您当前的代码位于将在UI线程上创建的方法(将抛出NetworkOnMainThreadException),因此您需要将代码移到线程而不是在主/ UI线程上运行,以阻止它在您的操作继续时阻止UI。

答案 2 :(得分:0)

当您尝试在主任务中进行网络呼叫时,会出现MainThreadException。通常屏幕和应用会在执行时冻结,因此Android禁止它。因此,在这种情况下,您必须创建AsyncTask

像这样创建AsyncTask

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

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(YourActivity.this);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progressDialog.setIndeterminate(true);
            progressDialog.setMessage("Please Wait");
            progressDialog.setCancelable(false);
            progressDialog.show();
        }

        @Override
        protected String doInBackground(String... params) {
            try {
                url = new URL(params[0]);
                urlConnection =(HttpURLConnection) url.openConnection();
                urlConnection.connect();
                urlConnection.setConnectTimeout(5000);
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
                envelope.dotNet = true;
                envelope.setOutputSoapObject(request);
                HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS);
            try  {
                httpTransport.call(SOAP_ACTION, envelope);
                Object response = envelope.getResponse();

            }catch (Exception exception)   {
                tvData1.setText(exception.toString()+"  Or enter number is not Available!");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return response;
        }

        private StringBuilder inputStreamToString(InputStream is) {
            String rLine = "";
            StringBuilder answer = new StringBuilder();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            try {
                while ((rLine = rd.readLine()) != null) {
                    answer.append(rLine);
                }
            } catch (Exception e) {
                MainActivity.this.finish();
            }
            return answer;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            progressDialog.dismiss();
            tvData1.setText(result.toString());
        }
    }

然后在你的onCreate()中你可以这样做

new MyTask().execute();