安卓设备调用Web服务失败,但在模拟器上正常

7
我几个月前开发了一些Android应用程序项目,其中包括:
  • GCM功能
  • Webservice调用
当时它运行良好。昨天我尝试在真实设备上运行它,并发现它无法进行任何webservice调用。 我原以为模拟器上也会出现同样的问题,但出乎我的意料,它在模拟器上工作正常。
我在真实设备上遇到的异常是:ConnectionTimeOutException。
我想知道发生了什么错误,以便解决这个问题。我不确定我应该发布哪些更多的信息。如果需要请告诉我。
AsyncTask<Void, Void, Boolean> gettingHttpOTP = new AsyncTask<Void, Void,Boolean>(){
HttpResponse httpresponse;
HttpClient client ;
JSONObject objSendjson;
HttpPost post ;
HttpEntity entity;
String result;
JSONObject objRetrievejson;

@Override
protected Boolean doInBackground(Void... arg0) {
client = new DefaultHttpClient();

HttpConnectionParams.setConnectionTimeout(client.getParams(), 50000);

objSendjson = new JSONObject();

 try
 {
    post = new HttpPost(Configurations.API_VERIFY_END_USER);


    objSendjson.put("Mobile_Number", gCountryCodeAndMobileNumber);
    objSendjson.put("Signature_Key", Configurations.SIGNATUREKEY);
    post.setHeader("Content-type", "application/json");
    post.setEntity(new StringEntity(objSendjson.toString(), "UTF-8"));
    httpresponse = client.execute(post);
    entity = httpresponse.getEntity();
     gHttpResponseCode=httpresponse .getStatusLine().getStatusCode();

     if(gHttpResponseCode==200)
     {
    gResponseText = EntityUtils.toString(entity);

    objRetrievejson=new JSONObject(gResponseText);

    gRecievedJsonOutput=objRetrievejson.getString("Result_Output");
    gRecievedJsonDescription=objRetrievejson.getString("Result_Message");
    gRecievedJsonCode=objRetrievejson.getString("Result_Code");
    gRecievedJsonStatus=objRetrievejson.getString("Result_Status");

 }
     else
     {
         gResponseText=null;
     }
 }
 catch(Exception errorException)
 {
    Log.d("Exception generated with response code = "+gHttpResponseCode,""+ 
           errorException);

 }
 return null;
}

我的网络服务正在互联网上运行,我尝试使用不同的ISP


编辑(2015年5月4日):

我不知道是什么原因导致了这个问题,但我没有更改任何代码,现在它又可以正常工作了。


@ImtiyazKhalani 我已经尝试过这个了... :/ - nobalG
你的服务在哪里运行?6小时前我已经问过了。如果你想让我发布什么,请问一下。你是真的这么想吗? - greenapps
恕我直言,我不能公开URL,但我知道它们很好用,因为我已经通过Google Chrome提供的API客户端进行了测试,并且还成功地从模拟器中发出了调用。我正在使用POST方法,我已经将我的REST API部署在JBOSS服务器上,并通过公共IP访问它......是的,我是认真的.. :)... @greenapps - nobalG
3
你不必发布完整的URL。我想知道的是你的服务在哪里运行。所以你可以回答“在互联网的某个地方”。或者它运行在我的笔记本电脑/电脑上,模拟器也在同一台电脑上。因此,它是一个公共IP。那很奇怪,为什么它不起作用。你的设备通过WiFi连接,使用与运行模拟器的PC相同的路由器吗? - greenapps
使用移动连接会失败吗?使用WiFi会失败吗? - greenapps
显示剩余18条评论
6个回答

1

nobalG,试试我的代码

这里是JSONParser类

public class JSONParser {

static InputStream is = null;
static JSONObject jObj = null;
static String json = "";

// constructor
public JSONParser() {

}

public JSONObject makeHttpRequest(String url, String method,
        List<NameValuePair> params) {
    Log.e("param--- is:-", "" + params);
    // Making HTTP request
    try {

        // check for request method
        if (method == "POST") {
            // request method is POST
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            httpPost.setEntity(new UrlEncodedFormEntity(params));

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();

        } else if (method == "GET") {
            // request method is GET
            DefaultHttpClient httpClient = new DefaultHttpClient();
            String paramString = URLEncodedUtils.format(params, "utf-8");
            url += "?" + paramString;
            Log.e("-------------------------->", paramString.toString());
            HttpGet httpGet = new HttpGet(url);

            HttpResponse httpResponse = httpClient.execute(httpGet);

            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();

        }

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8);

        StringBuilder sb = new StringBuilder();

        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");

        }

        Log.e("TAG", "sb.toString() >>>>>" + sb.toString());
        json = sb.toString();
        is.close();

    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    // try parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    // return JSON String
    return jObj;

}}

现在通过添加此Json类引用,使用post方法调用webservice,并将参数传递为我所传递的内容,并通过您的webservice响应获取数据。
class GetUserDetail extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(Login.this);
        pDialog.setMessage("Please wait Insert Record ....");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show()
    }

    protected String doInBackground(String... params) {

        try {
            // json class ref. from above class
            JSONParser jsonpd = new JSONParser();
            String url_login = "www.xyz.com/user_login.php"; // webservice url
            List<NameValuePair> params1 = new ArrayList<NameValuePair>();
            params1.add(new BasicNameValuePair("email", elogin_email
                    .getText().toString()));
            params1.add(new BasicNameValuePair("password", elogin_pass
                    .getText().toString()));
            JSONObject json = jsonpd.makeHttpRequest(url_login, "POST",
                    params1); // webservice call and json responce in json
            JSONObject mainJson = new JSONObject(json.toString());
            cnt = GlobalArea.successresult(mainJson);
            JSONArray json_contents = mainJson.getJSONArray("Success");
            for (int i = 0; i < json_contents.length(); i++) {
                JSONObject e = json_contents.getJSONObject(i);
                EMAIL = e.getString("email");
                CUSTOMER_ID = e.getString("customer_id");
                PASSWORD = elogin_pass.getText().toString();
            }
        } catch (JSONException e) {

        }
        return null;
    }

    protected void onPostExecute(String file_url) {

        try {
            pDialog.dismiss();
            if (cnt == 2) {
                Toast.makeText(getApplicationContext(),
                        "Check Email Id and Password", Toast.LENGTH_LONG)
                        .show();
            } else {
                Toast.makeText(getApplicationContext(),
                        ToastStrings.LoginMessage, Toast.LENGTH_LONG).show();
            }
        } catch (Exception e) {

        }
    }
}

对我来说它运行良好。使用它,它可能对你有帮助。


1

经过两年的经历,我怀疑真正的问题是Wifi连接,因为我们公司使用的防火墙设置。我建议每个遇到这个问题的人都必须检查一下他们公司的IT部门,因为他们是当天的罪魁祸首。


0
我在真实设备上遇到的异常是:ConnectionTimeOutException。
可能的情况是您的模拟器正在使用桌面/笔记本电脑上更快的互联网,而连接在那里没有超时。
在手机上,连接可能较差。尝试增加连接超时时间,如下所示:
    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used. 
    int timeoutConnection = 5000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 30000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

    HttpClient client = new DefaultHttpClient(httpParameters);

0
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

这里还有一个代码示例,展示如何实现此功能,它适用于REST服务,但您可能会发现一些有用的东西

public class RestClient {

private final static String TAG = "RestClient";

protected Context context;
private boolean authentication;
private ArrayList<NameValuePair> headers;
private String jsonBody;
private String message;
private ArrayList<NameValuePair> params;
private String response;
private int responseCode;
private String url;
// HTTP Basic Authentication
private String username;
private String password;

public RestClient(String url) {
    this.url = url;
    params = new ArrayList<NameValuePair>();
    headers = new ArrayList<NameValuePair>();

}

private static String convertStreamToString(InputStream is) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}

// Be warned that this is sent in clear text, don't use basic auth unless
// you have to.
public void addBasicAuthentication(String user, String pass) {
    authentication = true;
    username = user;
    password = pass;
}

public void addHeader(String name, String value) {
    headers.add(new BasicNameValuePair(name, value));
    Log.i(TAG, "Header Added: " + name + " " + value);
}

public void addParam(String name, String value) {
    params.add(new BasicNameValuePair(name, value));
}

public void execute(RequestMethod method) throws Exception {
    switch (method) {
        case GET: {
            HttpGet request = new HttpGet(url + addGetParams());
            request = (HttpGet) addHeaderParams(request);
            executeRequest(request, url);
            break;
        }
        case POST: {
            HttpPost request = new HttpPost(url);
            request = (HttpPost) addHeaderParams(request);
            request = (HttpPost) addBodyParams(request);
            executeRequest(request, url);
            break;
        }
        case PUT: {
            HttpPut request = new HttpPut(url);
            request = (HttpPut) addHeaderParams(request);
            request = (HttpPut) addBodyParams(request);
            executeRequest(request, url);
            break;
        }
        case DELETE: {
            HttpDelete request = new HttpDelete(url);
            request = (HttpDelete) addHeaderParams(request);
            executeRequest(request, url);
        }
    }
}

private HttpUriRequest addHeaderParams(HttpUriRequest request)
        throws Exception {
    for (NameValuePair h : headers) {
        request.addHeader(h.getName(), h.getValue());
    }

    if (authentication) {

        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(
                username, password);
        request.addHeader(new BasicScheme().authenticate(creds, request));
    }

    return request;
}

private HttpUriRequest addBodyParams(HttpUriRequest request)
        throws Exception {
    if (jsonBody != null) {

        request.addHeader("Content-Type", "application/json");
        if (request instanceof HttpPost)
            ((HttpPost) request).setEntity(new StringEntity(jsonBody,
                    "UTF-8"));
        else if (request instanceof HttpPut)
            ((HttpPut) request).setEntity(new StringEntity(jsonBody,
                    "UTF-8"));

    } else if (!params.isEmpty()) {
        if (request instanceof HttpPost)
            ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params,
                    HTTP.UTF_8));
        else if (request instanceof HttpPut)
            ((HttpPut) request).setEntity(new UrlEncodedFormEntity(params,
                    HTTP.UTF_8));
    }
    return request;
}

private String addGetParams() throws Exception {
    // Using StringBuffer append for better performance.
    StringBuffer combinedParams = new StringBuffer();
    if (!params.isEmpty()) {
        combinedParams.append("?");
        for (NameValuePair p : params) {
            combinedParams.append((combinedParams.length() > 1 ? "&" : "")
                    + p.getName() + "="
                    + URLEncoder.encode(p.getValue(), "UTF-8"));
        }
    }
    return combinedParams.toString();
}

public String getErrorMessage() {
    return message;
}

public String getResponse() {
    return response;
}

public int getResponseCode() {
    return responseCode;
}

public void setContext(Context ctx) {
    context = ctx;
}

public void setJSONString(String data) {
    jsonBody = data;
}

private void executeRequest(HttpUriRequest request, String url) {

    DefaultHttpClient client = new DefaultHttpClient();
    HttpParams params = client.getParams();

    // Setting 15 second timeouts
    HttpConnectionParams.setConnectionTimeout(params, 15 * 1000);
    HttpConnectionParams.setSoTimeout(params, 15 * 1000);

    HttpResponse httpResponse;

    try {
        httpResponse = client.execute(request);
        responseCode = httpResponse.getStatusLine().getStatusCode();
        message = httpResponse.getStatusLine().getReasonPhrase();

        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {

            InputStream instream = entity.getContent();
            response = convertStreamToString(instream);

            // Closing the input stream will trigger connection release
            instream.close();
        }

    } catch (ClientProtocolException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    } catch (IOException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    }
}

@Override
public String toString() {
    return "RestClient{" +
            "authentication=" + authentication +
            ", headers=" + headers +
            ", jsonBody='" + jsonBody + '\'' +
            ", message='" + message + '\'' +
            ", params=" + params +
            ", response='" + response + '\'' +
            ", responseCode=" + responseCode +
            ", url='" + url + '\'' +
            ", username='" + username + '\'' +
            ", password='" + password + '\'' +
            ", context=" + context +
            '}';
    }
}

为什么不使用AsyncTask,这与线程安全问题有关。 - BooNonMooN
请参考附在问题中的代码片段,我已经在使用AsyncTask。 - nobalG

0

这可能与DefaultHttpClient不是线程安全的有关。点击这里查看更多详细信息,以及这个答案中关于如何使用ThreadSafeClientConnManager使其线程安全的可能解决方案。祝你好运,并在解决了问题后给予反馈。


我正在研究这个问题。 - nobalG
似乎没有成功。您是否排除了DNS问题的可能性,通过输入IP而不是域名? - Plamen Petrov

0
可能听起来有点傻,但在任何情况下尝试连接互联网之前,始终建议检查互联网连接。

以下是一个简单的代码片段: 检测Android设备是否具有互联网连接

还可以尝试使用setconnectiontimeout()增加超时值。

希望这对您有所帮助 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接