Unable to call REST API in android

2020-07-18 09:29发布

问题:

I am trying to call a REST web service from my phone. I am using following code to complete this. I have only one activity which has a button and textview. Whenever i click on button it gives following error in logcat :

AndroidRuntime :: at android.os.Handler.dispatchMessage(Handler.java:92)

What i am doing wrong? how can i solve this ??? Following are my classes.

rest.java

public class Rest extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.start_rest);

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


    button.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            String url = "http://192.168.1.145/tst.php";

            RestService re = new RestService();             
            JSONObject jb =  RestService.doGet(url);

            TextView tv = (TextView) findViewById(R.id.txtView);                
            tv.setText(jb.toString());
        }
    });

  }
}

RestService.java

public class RestService {

public static JSONObject doGet(String url) {
    JSONObject json = null;

    HttpClient httpclient = new DefaultHttpClient();
    // Prepare a request object
    HttpGet httpget = new HttpGet(url);
    // Accept JSON
    httpget.addHeader("accept", "application/json");
    // Execute the request
    HttpResponse response;

    try {
        response = httpclient.execute(httpget);
        // Get the response entity
       // Log.e("myApp", "Issue is here...!");
        HttpEntity entity = response.getEntity();
        // If response entity is not null
        if (entity != null) {
            // get entity contents and convert it to string
            InputStream instream = entity.getContent();
            String result= convertStreamToString(instream);
            // construct a JSON object with result
            json=new JSONObject(result);
            // Closing the input stream will trigger connection release
            instream.close();
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // Return the json
    return json;
}

private static String convertStreamToString(InputStream is) {

    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();

    String line;
    try {

        br = new BufferedReader(new InputStreamReader(is));
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    return sb.toString();
}
}

回答1:

Having tried the code that you posted, I get the following exception (which I suspect you'll find the same in logcat if you look)

12-17 10:28:26.850    2182-2182/com.example.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    android.os.NetworkOnMainThreadException
            at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
            at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
            at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
            at java.net.InetAddress.getAllByName(InetAddress.java:214)
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
            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.example.app.RestService.doGet(RestService.java:31)
            at com.example.app.MainActivity$1.onClick(MainActivity.java:28)
            at android.view.View.performClick(View.java:4084)
            at android.view.View$PerformClick.run(View.java:16966)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

You get this because you're trying to do something across the network on the main thread, which is not allowed. (It's mentioned in the Google design guidelines here)

The best solution in this case would be to move the service call into an AsyncTask, which runs on a separate thread and doesn't block the UI.

Try this, I swapped out the URL for a freely available JSON web service that just returns the date

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

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


        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String url = "http://date.jsontest.com";
                new MyAsyncTask().execute(url);
            }
        });


    }
    class MyAsyncTask extends AsyncTask<String,Void,JSONObject> {

        @Override
        protected JSONObject doInBackground(String... urls) {
            return RestService.doGet(urls[0]);
        }

        @Override
        protected void onPostExecute(JSONObject jsonObject) {
            TextView tv = (TextView) findViewById(R.id.txtView);
            tv.setText(jsonObject.toString());
        }
    }

}


回答2:

Write an async task and do the network operation in that thread.

     public class myTask extends AsyncTask<String, JSONObject, Void> {

        private ProgressDialog dialog;
        private Context mContext;

        public myTask(Context mContext){
            this.mContext = mContext;

        }

        protected void onPreExecute() {
            this.dialog = new ProgressDialog(mContext);
            this.dialog.setCancelable(false);
            this.dialog.setMessage("please wait..");
            this.dialog.show();
        }

        protected JSONObject doInBackground(String... ids) {

            String url = "http://192.168.1.145/tst.php";
            RestService re = new RestService();             
            JSONObject jb =  RestService.doGet(url);

            return jb;
        }

       protected Void onPostExecute(JSONObject jb) {

            //get json data and set
        }
    }