【问题标题】:Android service fails to connect to server when the activities are in the background活动在后台时,Android 服务无法连接到服务器
【发布时间】:2016-12-22 18:33:34
【问题描述】:

这是我在 stackoverflow 上的第一篇文章,所以我希望我做的一切都是正确的。 我正在开发我的第一个 android 应用程序,并且在某些设备上遇到了奇怪的行为。我有一个前台服务,它会定期获取设备的位置,并使用带有延迟运行器的处理程序将其发送到服务器。在我的手机(Marshmallow,API 23)中一切正常,但是当应用程序的活动在后台时,使用运行 Lollipop(API 21)的小米手机的朋友无法连接到服务器。 这是将位置发送到服务器的函数:

    private void sendLocation(final String request_id, final String location ) {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(RestServiceConstants.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    String email = prefManager.pref.getString("UserEmail","");
    String password = prefManager.pref.getString("UserPassword","");

    Log.d(TAG,"sendLocation called");

    RestService service = retrofit.create(RestService.class);
    Call<StatusResponse> call = service.location("Basic "+ Base64.encodeToString((email + ":" + password).getBytes(),Base64.NO_WRAP),
            request_id,location);
    call.enqueue(new Callback<StatusResponse>() {
        @Override
        public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
            Log.d(TAG, "onResponse: raw: " + response.body());
            if (response.isSuccess() && response.body() != null){
                Log.d(TAG, "The location has been sent successfully");
                if(resendLocationHandler != null)
                    resendLocationHandler.removeCallbacksAndMessages(null);
            } else if (response.code() == 401){
                Log.i(TAG, "onCreate: User not logged in");
                prefManager.setIsLoggedIn(false);
            } else {
                Log.i(TAG, "sendLocation Unknown error occurred");
            }

        }

        @Override
        public void onFailure(Call<StatusResponse> call, Throwable t) {
            Log.i(TAG, "sendLocation Failed to get the server");
            if(resendLocationHandler == null)
                resendLocationHandler = new Handler();
            resendLocationHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    sendLocation(request_id, location);
                }
            }, resendFailedRequestDelay);

        }
    });
}

我不知道我还应该提供什么来帮助您诊断问题,因此请随时提出任何看似相关的要求。提前致谢

编辑:我所说的请求失败的意思是它触发了 onFailure 回调。回调中捕获的异常是:

java.net.ConnectException: Failed to connect to my_server_address:80
    at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:139)
    at okhttp3.internal.io.RealConnection.connect(RealConnection.java:108)
    at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:188)
    at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:127)
    at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
    at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:289)
    at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
    at okhttp3.RealCall.getResponse(RealCall.java:240)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
    at okhttp3.RealCall.access$100(RealCall.java:30)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:33)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:818)

【问题讨论】:

  • 欢迎您!它以什么方式失败?它什么都不做(即没有回调发生)还是有错误消息/调用堆栈?如果您调用了 onFailure,您可能希望将日志行更改为 Log.i(TAG, "...", t),以便从 Throwable 中获取信息。此外,您可能想打印 call arg 中的任何内容。
  • onFailure 确实被调用了,如果我得到更多信息,我会进行修改并更新你。
  • @SnildDolkow:我将从 throwable 获得的信息添加到我的帖子中。我希望你能看看它。提前致谢。
  • 好吧,这并没有说太多。来自call arg 的信息呢?
  • 其实这可能与某种“电池优化”有关,它可以阻止后台应用程序访问网络——参见reddit.com/r/Xiaomi/comments/4r6eld/…。如果是这样,可能是小米用户需要手动将你的应用添加到某个白名单中……

标签: android


【解决方案1】:

这可能与某种“电池优化”有关,它可能会阻止后台应用程序访问网络——例如,请参阅https://www.reddit.com/r/Xiaomi/comments/4r6eld/does_battery_optimization_ever_work_for/

在我对 MIUI 上的后台应用程序有一些问题后,我想通了 与 MIUI 中的省电功能有关。当我 只需将“管理应用程序的电池使用情况”设置为标准,后台应用程序 即使他们有自动运行权限,也很少工作。 “很少工作” 意思是:谷歌收件箱不同步,谷歌地图不跟踪,一些 基于位置的应用程序(如雨警报)不显示下雨通知, 等等。

我必须将所有这些应用程序都设置到例外列表中,所以 电池优化不会影响他们。 [...]

因此,小米用户(以及设备具有类似功能的用户)可能需要手动将您的应用添加到白名单中。

我不知道这些“优化”设置是否默认开启——我当然希望它们没有。

【讨论】:

  • 你可以发送这个意图:ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
【解决方案2】:

检查清单文件中添加的以下权限

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

【讨论】:

  • 我只有 INTERNET 权限,我会尝试 ACCESS_NETWORK_STATE 并接受你的回答,如果它有效:)
  • 我终于得到了修改版的反馈。可悲的是它仍然无法正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-12
  • 2020-01-24
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多