我尝试了两种不同的方法来从 Android 调用简单的 REST 方法;所说的 REST 方法——它适用于其他客户端——只返回一个 int val,例如 17。
以下两次尝试都是基于我在网上找到的代码。一个是这样的:
public void onFetchBtnClicked(View v){ if(v.getId() == R.id.FetchBtn){ Toast.makeText(getApplicationContext(), "你把按钮弄坏了,伙计。", Toast.LENGTH_SHORT).show() ; 新的 NetworkTask().execute(); } }
公共静态类 NetworkTask 扩展 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(标签,结果);}
使用上面的代码,以下代码行失败后:
result = httpclient.execute(request, handler) ;
......我明白了,“ *E/callWebService﹕ IOException in callWebService(). Connection to http://localhost:28642 refused*
”
这个问题可能是线程问题,正如我在 O'Reilly 的 Mednieks、Dornin、Meike 和 Nakamura 所著的“Programming Android”一书中读到的:“ AsyncTask 是运行小型异步任务的便捷工具。请记住 doInBackground 方法在不同的线程上运行!它不能写入任何从另一个线程可见的状态或从另一个线程读取任何可写的状态。这包括它的参数。
与我的其他尝试:
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;
}
...在遇到相同的问题行(result = httpclient.execute(request,handler))后,调试器将我转储到 View.class 中。为什么会这样,我不知道*,但我认为问题的症结所在,如 logcat 中的 err msgs 所示:“由:android.os.NetworkOnMainThreadException 引起”
*可能是因为在 UI(视图)线程中尝试了一些不愉快的事情。
此外(不是什么大问题,但也许“有趣”):当在它之后进行方法调用时,Toast 不会弹出(否则它会起作用)。
(Web API) 服务器在其对应的 Controller 方法中设置了断点,但从未到达。如前所述,服务器正在运行,并且可以很好地响应其他(Windows 应用程序)客户端。
必须有一种从 Android 调用 RESTful 方法的直接方法。但是什么/如何?
更新
我现在也试过了,这样称呼它:
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”异常。
更新 2
我想这是迄今为止我最接近的一次。在这种情况下,服务器可能是罪魁祸首,因为使用以下代码:
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
....抛出的异常是:
libcore.io.ErrnoException:连接失败:ECONNREFUSED(连接被拒绝)无法连接到 localhost/127.0.0.1(端口 28642):连接失败:ECONNREFUSED(连接被拒绝)
...并且 Android 应用程序继续运行(在其他示例中它崩溃了)。
为什么我的服务器拒绝连接?
更新 3
我想了想我明白了:我忘了用 URL 传递序列号。但即使这样做了,它也失败了。
我在服务器应用程序中有一个断点,在 Controller 方法中;同样,在 Repository 方法中,但它们永远不会到达。
有什么问题?
“localhost”是不是使用错误的东西(在 URL 中)?我应该改用计算机的名称吗?
URL(按字面意思传递为“ http://localhost:28642/api/Departments/GetCount?serialNum=4242
”)是否需要逐字逐句?
更新 4
将“locohost”更改为机器名称,我得到“没有与主机名关联的地址”,所以这不是问题......
奇怪的是,这条线运行良好:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
...而这是抛出/捕获异常之前的最后一行:
in = new BufferedInputStream(urlConnection.getInputStream());
不过,看着这个,也许我需要摆脱困境;但是当你已经有双重打击时,比如在“http:”之后,你必须做三重打击吗?还是四连击?肯定不是天花板蜡……?