如何从Android调用RESTful方法? [英] How to call a RESTful Method from Android?

查看:232
本文介绍了如何从Android调用RESTful方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试了两种不同的方法来从Android调用简单的REST方法;所说的REST方法(可从其他客户端使用)仅返回一个int val,例如17.

I've tried two different ways to call a simple REST method from Android; said REST method - which works from other clients - simply returns an int val such as 17.

以下两种尝试均基于我在网上找到的代码.一个是这样的:

Both of the following attempts were based on code I found online. One is like so:

public void onFetchBtnClicked(View v){ if(v.getId()== R.id.FetchBtn){ Toast.makeText(getApplicationContext(),您将按钮捣碎了,伙计.",Toast.LENGTH_SHORT).show(); 新的NetworkTask().execute(); } }

public void onFetchBtnClicked(View v){ if(v.getId() == R.id.FetchBtn){ Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show(); new NetworkTask().execute(); } }

公共静态类NetworkTask扩展了AsyncTask {

public static class NetworkTask extends AsyncTask {

@Override
protected String doInBackground(Void... params) {
    final String TAG;
    TAG = "callWebService";
    String deviceId = "Android Device";

    HttpClient httpclient = new DefaultHttpClient();
    HttpGet request = new HttpGet("http://localhost:28642/api/Departments/GetCount");
    request.addHeader("deviceId", deviceId);

    ResponseHandler<String> handler = new BasicResponseHandler();
    String result = "";

    try
    {
        result = httpclient.execute(request, handler);
    }
    catch (ClientProtocolException e)
    {
        e.printStackTrace();
        Log.e(TAG, "ClientProtocolException in callWebService(). " + e.getMessage());
    }
    catch (IOException e)
    {
        e.printStackTrace();
        Log.e(TAG, "IOException in callWebService(). " + e.getMessage());
    }

    httpclient.getConnectionManager().shutdown();
    Log.i(TAG, "**callWebService() successful. Result: **");
    Log.i(TAG, result);
    Log.i(TAG, "*****************************************");

    return result;
}

@Override
protected void onPostExecute(String result) {
    final String TAG;
    TAG = "onPostExecute";
    if (null != result)

Log.i(TAG,结果); }

Log.i(TAG, result); }

使用上面的代码,在以下代码行失败之后:

With the code above, after the following line of code fails:

result = httpclient.execute(request, handler) ;

...我得到"*E/callWebService﹕ IOException in callWebService(). Connection to http://localhost:28642 refused*"

这个问题可能是线程问题,正如我在Mednieks,Dornin,Meike和Nakamura的O'Reilly的"Android编程"一书中读到的那样:" AsyncTask是用于运行小型异步任务的便捷工具.只需记住doInBackground方法在不同的线程上运行即可!它一定不能写入从另一个线程可见的任何状态,也不能读取从另一个线程可写的任何状态.这包括其参数."

This problem may be a threading issue, as I read this in O'Reilly's "Programming Android" book by Mednieks, Dornin, Meike, and Nakamura: "AsyncTask is a convenenient tool for running small, asynchronous tasks. Just remember that the doInBackground method runs on a different thread! It must not write any state visible from another thread or read any state writable from another thread. This includes its parameters."

以我的另一尝试:

public void onFetchBtnClicked(View v){
    if(v.getId() == R.id.FetchBtn){
        Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show();
        callWebService("http://localhost:28642/api/Departments/GetCount");
    }
}

public String callWebService(String requestUrl)
{
    final String TAG;
    TAG = "callWebService";
    String deviceId = "Android Device";

    HttpClient httpclient = new DefaultHttpClient();
    HttpGet request = new HttpGet(requestUrl);
    request.addHeader("deviceId", deviceId);

    ResponseHandler<String> handler = new BasicResponseHandler();
    String result = "";

    try
    {
        result = httpclient.execute(request, handler);
    }
    catch (ClientProtocolException e)
    {
        e.printStackTrace();
        Log.e(TAG, "ClientProtocolException in callWebService(). " + e.getMessage());
    }
    catch (IOException e)
    {
        e.printStackTrace();
        Log.e(TAG, "IOException in callWebService(). " + e.getMessage());
    }

    httpclient.getConnectionManager().shutdown();
    Log.i(TAG, "**callWebService() successful. Result: **");
    Log.i(TAG, result);
    Log.i(TAG, "*****************************************");

    return result;
}

...调试器在遇到同一问题行后将我转储到View.class中(结果= httpclient.execute(request,handler)).为什么这样做,我不知道*,但是我认为问题的症结,如logcat中的err msgs所指出的:由:android.os.NetworkOnMainThreadException引起"

...the debugger dumps me into View.class after hitting that same problem line (result = httpclient.execute(request, handler)). Why it does that, I don't know*, but I think the crux of the problem, as indicated by err msgs in logcat, is: "Caused by: android.os.NetworkOnMainThreadException"

*也许是因为正在UI(视图)线程中尝试了一些不愉快的事情.

*Maybe because something untoward is being attempted within the UI (View) thread.

也(不是什么大问题,但也许有趣"):在执行方法调用后,Toast不会弹出(否则会起作用).

Also (not a big deal, but "interesting," perhaps): the Toast doesn't pop up when a method call is made after it (it works otherwise).

(Web API)服务器在其相应的Controller方法中设置了一个断点,但从未到达过.如前所述,服务器正在运行,并且对其他(Windows应用程序)客户端的响应也很好.

The (Web API) server has a breakpoint set in its corresponding Controller method, but it is never reached. As mentioned, the server is running, and responds just fine to other (Windows app) clients.

必须有一种从Android调用RESTful方法的简单方法.但是什么/如何?

There must be a somewhat straightforward way of calling a RESTful method from Android. But what/how?

我尝试了,现在,也这样称呼它:

I tried this, now, too, calling it like so:

RestClient client = new RestClient("http://localhost:28642/api/Departments/GetCount");

    try {
        client.Execute(RestClient.RequestMethod.GET);
    } catch (Exception e) {
        e.printStackTrace();
    }

    String response = client.getResponse();
    Log.i("CZECH_THIS", response);

...但是也很(或似乎还是)抛出"NetworkOnMainThread"异常.

...but it also is (or seems, anyway) happy to throw the "NetworkOnMainThread" exception.

我认为,这是我到目前为止最接近的.在这种情况下,也许服务器是罪魁祸首,因为使用以下代码:

This is the closest I've gotten so far, I think. Maybe the server is the culprit in this case, because with this code:

public void onFetchBtnClicked(View v){
    if(v.getId() == R.id.FetchBtn){
        Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show();
    new CallAPI().execute("http://localhost:28642/api/Departments/GetCount");
    }
}

public static class CallAPI extends AsyncTask<String, String, String> {

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

        String urlString=params[0]; // URL to call
        String resultToDisplay = "";
        InputStream in = null;

        // HTTP Get
        try {
            URL url = new URL(urlString);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedInputStream(urlConnection.getInputStream());

        } catch (Exception e ) {
            System.out.println(e.getMessage());
            return e.getMessage();
        }
        return resultToDisplay;

    }

    protected void onPostExecute(String result) {
        Log.i("FromOnPostExecute", result);
    }

} // end CallAPI

....引发的异常是:

....the exception that is thrown is:

libcore.io.ErrnoException:连接失败:ECONNREFUSED(连接被拒绝) 无法连接到localhost/127.0.0.1(端口28642):连接失败:ECONNREFUSED(连接被拒绝)

libcore.io.ErrnoException: connect failed: ECONNREFUSED (Connection refused) failed to connect to localhost/127.0.0.1 (port 28642): connect failed: ECONNREFUSED (Connection refused)

...并且Android应用继续运行(在其他示例中,该应用崩溃了).

...and the Android app continues to run (it falls over in the other examples).

为什么我的服务器拒绝连接?

Why is my server refusing the connection?

我想了一会儿:我忘了用URL传递序列号.但是即使这样做,它仍然会失败.

I thought for a minute I had it: I forgot to pass the serial Num with the URL. But even after doing so, it fails.

我在服务器应用程序的Controller方法中有一个断点;同样,在存储库"方法中,但从未达到它们.

I have a breakpoint in the server app, in the Controller method; also, in the Repository method, but they are never reached.

可能是什么问题?

本地主机"使用的是错误的东西(在URL中)吗?我应该改用计算机的名称吗?

Is "localhost" the wrong thing to use (in the URL)? Should I use the name of the computer instead?

是否需要逐字记录URL(字面传递为"http://localhost:28642/api/Departments/GetCount?serialNum=4242")?

Does the URL (passed literally as "http://localhost:28642/api/Departments/GetCount?serialNum=4242") need to be verbatimized?

将"locohost"更改为计算机名称,我得到与主机名无关联的地址",所以这不是问题...

Changing the "locohost" to the machine name, I get "No address associated with hostname" so that's not the problem...

不过,奇怪的是,此行运行正常:

Oddly, though, this line runs fine:

HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

...这是引发/捕获异常之前的最后一行:

...whereas this is the last line before the exception is thrown/caught:

in = new BufferedInputStream(urlConnection.getInputStream());

看着这个,也许我需要逃避我的重击;但是当您已经有两次重击时,例如"http:"之后,是否需要进行三次重击?还是四重w?当然不是天花板蜡...?

Looking at this, though, perhaps I need to escape my whacks; but when you already have double-whacks, as in after "http:", do you have to do triple-whacks? Or quadruple whacks? Surely not ceiling wax...?

推荐答案

我现在可以正常使用了. 此处.

I've got it working now. There's an article about it here.

这是其中的代码,没有任何解释:

This is the code from there without any explanation:

public class MainActivity extends ActionBarActivity {

    private GetDepartmentsCount _getDeptsCount;

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

        Button getDeptsCountBtn = (Button)findViewById(R.id.DeptsCountBtn);
        getDeptsCountBtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                _getDeptsCount = new GetDepartmentsCount();
                _getDeptsCount.execute("http://10.0.2.2:28642/api/Departments/GetCount?serialNum=4242");
            }
        });
    }

    @Override
    public void onStop() {
        super.onStop();
        _getDeptsCount.cancel(true);
    }

    private class GetDepartmentsCount extends AsyncTask<String, String, String> {

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

            String urlString = params[0]; // URL to call
            String result = "";

            // HTTP Get
            try {
                URL url = new URL(urlString);
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = urlConnection.getInputStream();
                if (null != inputStream)
                    result = IOUtils.toString(inputStream);
            } catch (Exception e) {
                System.out.println(e.getMessage());
                return e.getMessage();
            }
            return result;
        }

        @Override
        protected void onPostExecute(String result) {
            EditText dynCount = (EditText)findViewById(R.id.dynamicCountEdit);
            dynCount.setText(result + " records were found");
            Log.i("FromOnPostExecute", result);
        }
    } 

}

这篇关于如何从Android调用RESTful方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆