如何从Android调用RESTful方法? [英] How to call a RESTful Method from Android?
问题描述
我尝试了两种不同的方法来从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屋!