Android 尝试 POST REST API,应用因致命错误而崩溃

Android trying to POST to REST API, app crashing with Fatal Error

经过一番阅读,我已经确定了这个用于向 REST API 发送 POST 请求的基本代码:



    package com.theroom.TestProject;

    import android.app.Activity;
    //import android.content.Context;
    import android.os.Bundle;
    import android.telephony.TelephonyManager;
    import android.view.View;
    import android.widget.*;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.StatusLine;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.json.JSONObject;

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.Comparator;

    public class TestActivity extends Activity {
        private EditText username=null;
        private EditText  password=null;
        private Button login;
        /**
         * Called when the activity is first created.
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            Spinner spinner = (Spinner) findViewById(R.id.country_prefix);
            ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.country_codes, android.R.layout.simple_spinner_item);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            Comparator comparator = new CountryComparator();
            adapter.sort(comparator);
            spinner.setAdapter(adapter);
            TelephonyManager tMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    //        String mPhoneNumber = tMgr.getLine1Number();
            String CountryCode = tMgr.getSimCountryIso();
            CountryToPhonePrefix CP = new CountryToPhonePrefix();
            String PhoneCountryCode = CP.prefixFor(CountryCode.toUpperCase());
            Integer pos = adapter.getPosition(PhoneCountryCode);
            spinner.setSelection(pos);
            TextView PhoneNumberTV = (TextView) findViewById(R.id.login_Text);
    //        PhoneNumberTV.setText(PhoneCountryCode);
    //        this.getWindow().setBackgroundDrawable();
        }

        public void ToastPhoneNumber(View view) throws IOException {
            Toast toast = new Toast(getApplicationContext());
            TextView PhoneTV = (TextView) findViewById(R.id.login_Text);
            TelephonyManager tMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
            String CountryCode = tMgr.getSimCountryIso();
            CountryToPhonePrefix CP = new CountryToPhonePrefix();
            String PhoneCountryCode = CP.prefixFor(CountryCode.toUpperCase());

            HttpClient httpClient = new DefaultHttpClient();
            HttpPost PostRequest = new HttpPost("http://10.0.0.10:8000/api/v1/register");
            JSONObject data = new JSONObject();
            StringEntity se = new StringEntity(data.toString());
            PostRequest.setEntity(se);
            PostRequest.setHeader("Accept", "application/json");
            PostRequest.setHeader("Content-type", "application/json");
            HttpResponse response = httpClient.execute(PostRequest);

            StatusLine statusLine = response.getStatusLine();
            if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                String responseString = out.toString();
                out.close();
                toast.makeText(this, responseString, Toast.LENGTH_SHORT).show();
                //..more logic
            } else{
                //Closes the connection.
                response.getEntity().getContent().close();
                throw new IOException(statusLine.getReasonPhrase());
            }


        }
    }

当我 运行 代码并单击按钮激活 ToastPhoneNumber 方法时(以前是为了这个,现在它应该要求 API 发送验证短信),这就是我进入 logcat:

02-04 23:11:04.492      820-820/com.theroom.TestProject V/Zygote﹕ Switching descriptor 34 to /dev/null
02-04 23:11:04.492      820-820/com.theroom.TestProject V/Zygote﹕ Switching descriptor 9 to /dev/null
02-04 23:11:04.492      820-820/com.theroom.TestProject D/dalvikvm﹕ Late-enabling CheckJNI
02-04 23:11:04.512      820-820/com.theroom.TestProject I/dalvikvm﹕ Enabling JNI app bug workarounds for target SDK version 10...
02-04 23:11:04.552      820-820/com.theroom.TestProject D/ActivityThread﹕ handleBindApplication:com.theroom.TestProject
02-04 23:11:04.552      820-820/com.theroom.TestProject D/ActivityThread﹕ setTargetHeapUtilization:0.75
02-04 23:11:04.552      820-820/com.theroom.TestProject D/ActivityThread﹕ setTargetHeapMinFree:2097152
02-04 23:11:04.802      820-820/com.theroom.TestProject I/Timeline﹕ Timeline: Activity_idle id: android.os.BinderProxy@418911a8 time:412893749
02-04 23:11:14.212      820-820/com.theroom.TestProject D/AndroidRuntime﹕ Shutting down VM
02-04 23:11:14.212      820-820/com.theroom.TestProject W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x415dedb8)
02-04 23:11:14.222      820-820/com.theroom.TestProject E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.theroom.TestProject, PID: 820
    java.lang.IllegalStateException: Could not execute method of the activity
            at android.view.View.onClick(View.java:3830)
            at android.view.View.performClick(View.java:4445)
            at android.view.View$PerformClick.run(View.java:18446)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5146)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at android.view.View.onClick(View.java:3825)
            at android.view.View.performClick(View.java:4445)
            at android.view.View$PerformClick.run(View.java:18446)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5146)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: android.os.NetworkOnMainThreadException
            at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
            at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
            at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
            at libcore.io.IoBridge.connect(IoBridge.java:112)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:460)
            at java.net.Socket.connect(Socket.java:833)
            at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
            at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
            at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
            at com.theroom.TestProject.TestActivity.ToastPhoneNumber(TestActivity.java:73)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at android.view.View.onClick(View.java:3825)
            at android.view.View.performClick(View.java:4445)
            at android.view.View$PerformClick.run(View.java:18446)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5146)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
            at dalvik.system.NativeStart.main(Native Method)

你能帮我找出问题所在吗?我发现 Java 的异常很难诊断。它不像 PHP 使用起来那么简单和直观,例如 :(

Caused by: android.os.NetworkOnMainThreadException

您正在尝试从主线程进行网络调用,这在 android 中是不允许的。

从方法 ToastPhoneNumber(View view)

创建一个异步任务
MyTask task = new MyTask()
task.execute();

和任务:

public class MyTask extends AsyncTask<String, Void, String> {
    MyTask() {}
    @Override
    protected Boolean doInBackground(String... params) {

        try {
           // REST CALL
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        if (success) {
            // handle post execute
        }
    }

    @Override
    protected void onCancelled() {

    }
}

这应该有用,希望对您有所帮助!