0

这是一个有点复杂的问题,因为我不知道确切的问题。主要问题是从我们的 REST 服务器从我们的 Android 应用程序获取非常小的数据包需要很长时间。我会详细描述它,希望你能帮助我。

问题

在以下情况下,数据检索速度足够快(+/- 100 毫秒):

  • 与 WiFi 连接
  • 与 HSDPA 连接
  • 在网络设置(延迟和速度)设置为 GPRS 的 Android 模拟器上运行

但是,当我在连接不良(3G 而不是 HSDPA)的位置使用电话时,调用服务可能需要 4 秒(AsyncTask 上的当前超时)。

安卓

这是用于与服务通信的代码:

 /**
 * Get json string from service
 *
 * @param urlString url of service
 * @return json result from service
 */
private String callService(String urlString) {
    InputStream in = null;
    HttpURLConnection c = null;
    Scanner s = null;
    String json = null;
    try {
        URL url = new URL(urlString);
        Log.i(getClass().getName() + ".callService()", "start calling service: " + url);
        long start = java.lang.System.currentTimeMillis();
        try {
            setAuthentication();
            c = (HttpURLConnection) url.openConnection();
            c.connect();
            in = new BufferedInputStream(c.getInputStream());
            s = new Scanner(in);
            s.useDelimiter("\\A");
            json = s.next();

        } catch (IOException e) {
            Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
        }
        Log.i(getClass().getName() + ".callService()", "complete calling service: (" + (System.currentTimeMillis() - start) + " ms) " + url);
        return json;
    } catch (Exception e) {
        Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
    } finally {
        if (s != null) {
            s.close();
        }
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
            }
        }
        if (c != null) {
            c.disconnect();
        }
    }
    return json;
}

我尝试了几种方法来调用它,但目前这是使用 AsyncTask 完成的:

    /**
 * Retrieve json from service
 *
 * @param url url of service
 * @return json
 */
public String getJsonFromServiceBasic(String url) {
        ServiceTask task = new ServiceTask();
        try {
            return task.execute(url).get(4000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " interrupt exception: " + e.getMessage(), e);
        } catch (ExecutionException e) {
            Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " execution exception: " + e.getMessage(), e);
        } catch (TimeoutException e) {
            task.cancel(true);
            Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " timeout exception: " + e.getMessage(), e);
        } catch (Exception e) {
            Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " timeout exception: " + e.getMessage(), e);
        }
        return null;
}


/**
 * AsyncTask way of calling service
 */
class ServiceTask extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... urls) {
        String json = callService(urls[0]);
        return json;
    }
}

AndroidManifest.xml:

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

服务

我不认为这是问题所在,因为它与 HSDPA 一起工作得足够快,但我不确定。代理后面的 tomcat7 上的 Restlet 服务。我们使用 ChallengeAuthenticator 进行身份验证。

4

1 回答 1

0

我通过切换到 Apache 的 HttpClient 解决了这个问题。我不确定为什么这是 Google 建议使用 HttpURLConnection 的解决方案,但对我来说这是可行的。

使用此方法代替 callService 方法将解决我上网速度慢的问题。

private String callServiceClient(String urlString) {

    String json = null;

    HttpParams httpParams = new BasicHttpParams();
    int connection_Timeout = 5000;
    HttpConnectionParams.setConnectionTimeout(httpParams, connection_Timeout);
    HttpConnectionParams.setSoTimeout(httpParams, connection_Timeout);

    DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
    httpClient.getCredentialsProvider().setCredentials(new AuthScope(null, -1),
            new UsernamePasswordCredentials(user, password));

    HttpGet httpget = new HttpGet(urlString);

    // Execute the request
    HttpResponse response;
    try {
        response = httpClient.execute(httpget);
        // Examine the response status
        StatusLine responseCode = response.getStatusLine();
        Log.i(getClass() + ".callServiceClient()", "responsecode: " + responseCode);
        if (responseCode.getStatusCode() != HttpStatus.SC_OK) {
            return json;
        }

        // Get hold of the response entity
        HttpEntity entity = response.getEntity();
        // If the response does not enclose an entity, there is no need
        // to worry about connection release

        if (entity != null) {

            // A Simple JSON Response Read
            InputStream instream = entity.getContent();
            json = convertStreamToString(instream);
            // now you have the string representation of the HTML request
            instream.close();
        }
    } catch (ClientProtocolException e) {

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

    return json;
}
于 2014-03-11T09:04:35.053 回答