Android service fails to connect to server when th

2019-07-17 06:37发布

this is my first post on stackoverflow so I hope I am doing everything correctly. I am developing my first android App and I am experiencing weird behavior on some devices. I have a foreground service that periodically obtains the location of the device and I use a handler with a delayed runner to send it to a server. In my phone (Marshmallow, API 23) everything is working fine, but a friend who uses a Xiaomi phone running Lollipop (API 21) fails to connect to the server when the App's activities are in the background. This is the function that sends the location to the server:

    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);

        }
    });
}

I don't know what else should I provide to help you diagnose the issue so feel free to request whatever may seem relevant. Thanks in advance

Edit: what I mean by the request failing is that it triggers the onFailure callback. The exception caught in the callback is:

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)

标签: android
2条回答
兄弟一词,经得起流年.
2楼-- · 2019-07-17 06:55

Check following permission added in manifest file

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
查看更多
啃猪蹄的小仙女
3楼-- · 2019-07-17 07:18

It may be related some kind of "Battery optimization" which could prevent background apps from accessing the network -- see, for example, https://www.reddit.com/r/Xiaomi/comments/4r6eld/does_battery_optimization_ever_work_for/

after i had some problems with background apps on MIUI, i figured it hat something to do with the battery saver feature in MIUI. When i just set "Manage apps' battery usage" to standard, the background apps rarely work, even if they have autorun permission. "Rarely work" means: Google Inbox does not sync, Google Maps does not track, some location based apps (like Rain Alarm) do not show rain notifications, and so on.

I had to set EVERY of these apps to the exception list, so that the battery optimization does not affect them. [...]

So, it may be that Xiaomi users (and users whose devices have similar functionality) need to manually add your app to a whitelist.

I don't know if "optimization" settings like these are on by default -- I would certainly hope they aren't.

查看更多
登录 后发表回答