Geofencing: Ошибка HTTP-запроса при отправке через фоновую службу. Выдает UnknownHostException

Я реализовал Geofence в приложении для Android. Я перешел по этой ссылке, чтобы реализовать Geofence в приложении. Я использую библиотеку «Модернизация» для вызова запроса «HTTP».


Приложение имеет следующие разрешения:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


Вот мой код «IntentService»:

public class GeofenceService extends IntentService
{

    private static  final String TAG = GeofenceService.class.getName();


    public static final int GEOFENCE_NOTIFICATION_ID = 0;


    public GeofenceService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Retrieve the Geofencing intent
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);


        createLoggerFile();
        // Handling errors
        if ( geofencingEvent.hasError() ) {
            String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
            Logger.Important(true,  TAG, "onHandleIntent() :: errorMessage : "+errorMsg );
            return;
        }

        // Retrieve GeofenceTrasition
        int geoFenceTransition = geofencingEvent.getGeofenceTransition();
        // Check if the transition type
        if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ||
                geoFenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL)
        {
            Log.d(TAG, "onHandleIntent() :: geoFenceTransition : " + geoFenceTransition);
            // Get the geofence that were triggered
            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
            // Create a detail message with Geofences received
            String geofenceTransitionDetails = getGeofenceTrasitionDetails(geoFenceTransition, triggeringGeofences );
            // Send notification details as a String
            sendNotification( geofenceTransitionDetails );

        }
    }

    // Create a detail message with Geofences received
    private String getGeofenceTrasitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
        // get the ID of each geofence triggered
        ArrayList<String> triggeringGeofencesList = new ArrayList<>();
        for ( Geofence geofence : triggeringGeofences ) {
            triggeringGeofencesList.add( geofence.getRequestId() );
        pingGoogle();  // here is I am pinging google

        callingHttpRequest(); // calling Http request. Also I called this request through application class, but still it is not worked in background.


        }


        String status = null;
        if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER )
            status = "Entering ";
        else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
            status = "Exiting ";
        else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL )
            status = "Staying ";
        return status + TextUtils.join( ", ", triggeringGeofencesList);
    }

    // Send a notification
    private void sendNotification( String msg ) {
        Log.d( TAG, "sendNotification: " + msg );

        // Intent to start the main Activity
        Intent notificationIntent = new Intent(getApplicationContext(), DrawerActivity.class);;

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(DrawerActivity.class);
        stackBuilder.addNextIntent(notificationIntent);
        PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

        // Creating and sending Notification
        NotificationManager notificatioMng =
                (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
        notificatioMng.notify(
                GEOFENCE_NOTIFICATION_ID,
                createNotification(msg, notificationPendingIntent));
    }

    // Create a notification
    private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
        notificationBuilder
                .setSmallIcon(R.drawable.ic_phi_notification_logo)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.geo))
                .setColor(Converter.getColor(getApplicationContext(), R.color.default_pure_cyan))
                .setContentTitle(JsonKey.TRIGGER)
                .setContentText(msg)
                .setContentIntent(notificationPendingIntent)
                .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
                .setAutoCancel(true);
        return notificationBuilder.build();
    }

    // Handle errors
    private static String getErrorString(int errorCode) {
        switch (errorCode) {
            case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
                return "GeoFence not available";
            case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
                return "Too many GeoFences";
            case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
                return "Too many pending intents";
            default:
                return "Unknown error.";
        }
    }



 private void callingHttpRequest() {

     HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .readTimeout(10, TimeUnit.SECONDS)
                .connectTimeout(10 / 2, TimeUnit.SECONDS)
                .sslSocketFactory(sslSocketFactory().getSocketFactory())
                .build();

    Gson gson = new GsonBuilder()
                .setLenient()
                .create();

             Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();


            API api = retrofit.create(***.class);


            Call<ResponseBody> req = api.callGeofencingTrigger(***);

            req.enqueue(new Callback<ResponseBody>() {

                @Override
                public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                    try {
                        String string = response.body().string();
                        Log.d (TAG, "onResponse()  :: success");

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

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    t.printStackTrace();
                   Log.d (TAG, "onFailure()  :: t : "t.getMessage());

                }

            });

    }
}

Всякий раз, когда устройство получает триггер геозоны, оно работает нормально и выдает надлежащие уведомления о триггере, когда приложение находится в фоновом режиме или на переднем плане (вход / задержка / выход) или даже если пользователь убивает приложение из недавних задач. Когда я вызываю HTTP-запрос, когда приложение находится на переднем плане, оно работает нормально и печатает успех в журнале.

onResponse()  :: success

Но когда приложение уничтожается из-за недавних задач и устройство получает какой-либо триггер геозоны (вход/задержка/выход), тогда HTTP-запрос не выполняется должным образом. Это дает :

onFailure() :: t : 
</br>java.net.UnknownHostException: Unable to resolve host
"host_name": No address associated with hostname

где host_name — адрес сервера.

Я пингую google или IP-адрес 8.8.8.8 из фоновой службы. Все еще сталкиваются с теми же проблемами. Это также отлично работает, когда приложение находится на переднем плане, но после его закрытия оно не работает.

Итак, почему эта ошибка? Сетевая связь не звонит, когда приложение не находится в последних задачах?



‹-------------------------------------------------------------------------- -------------------------------------------------- ----------------------------->
Я пытался сделать следующее. Получив ответы от @Xavier и @Stevensen


Я использую firebase-jobscheduler в своем приложении для вызова HTTP запроса. Вот мой код:

В моем манифесте я добавил следующую службу:

 <service
            android:exported="false"
            android:name="com.****.service.TriggerJobService">
            <intent-filter>
                <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
            </intent-filter>
        </service>


Это мой модифицированный класс GeofenceService. Я только что удалил callingHttpRequest() и добавил запланированное задание, вызвав функцию scheduleJob() в функции getGeofenceTrasitionDetails(). И код такой же, как есть.

public class GeofenceService extends IntentService
    {

        private static  final String TAG = GeofenceService.class.getName();


        public static final int GEOFENCE_NOTIFICATION_ID = 0;


        public GeofenceService() {
            super(TAG);
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            // Retrieve the Geofencing intent
            GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);


            createLoggerFile();
            // Handling errors
            if ( geofencingEvent.hasError() ) {
                String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
                Logger.Important(true,  TAG, "onHandleIntent() :: errorMessage : "+errorMsg );
                return;
            }

            // Retrieve GeofenceTrasition
            int geoFenceTransition = geofencingEvent.getGeofenceTransition();
            // Check if the transition type
            if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                    geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ||
                    geoFenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL)
            {
                Log.d(TAG, "onHandleIntent() :: geoFenceTransition : " + geoFenceTransition);
                // Get the geofence that were triggered
                List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
                // Create a detail message with Geofences received
                String geofenceTransitionDetails = getGeofenceTrasitionDetails(geoFenceTransition, triggeringGeofences );
                // Send notification details as a String
                sendNotification( geofenceTransitionDetails );

            }
        }

        // Create a detail message with Geofences received
        private String getGeofenceTrasitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
            // get the ID of each geofence triggered
            ArrayList<String> triggeringGeofencesList = new ArrayList<>();
            for ( Geofence geofence : triggeringGeofences ) {
                triggeringGeofencesList.add( geofence.getRequestId() );

            scheduleJob(); // <code>**Here I schedule job**</code>


            }


            String status = null;
            if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER )
                status = "Entering ";
            else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
                status = "Exiting ";
            else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL )
                status = "Staying ";
            return status + TextUtils.join( ", ", triggeringGeofencesList);
        }

        // Send a notification
        private void sendNotification( String msg ) {
            Log.d( TAG, "sendNotification: " + msg );

            // Intent to start the main Activity
            Intent notificationIntent = new Intent(getApplicationContext(), DrawerActivity.class);;

            TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
            stackBuilder.addParentStack(DrawerActivity.class);
            stackBuilder.addNextIntent(notificationIntent);
            PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

            // Creating and sending Notification
            NotificationManager notificatioMng =
                    (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
            notificatioMng.notify(
                    GEOFENCE_NOTIFICATION_ID,
                    createNotification(msg, notificationPendingIntent));
        }

        // Create a notification
        private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
            notificationBuilder
                    .setSmallIcon(R.drawable.ic_phi_notification_logo)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.geo))
                    .setColor(Converter.getColor(getApplicationContext(), R.color.default_pure_cyan))
                    .setContentTitle(JsonKey.TRIGGER)
                    .setContentText(msg)
                    .setContentIntent(notificationPendingIntent)
                    .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
                    .setAutoCancel(true);
            return notificationBuilder.build();
        }

        // Handle errors
        private static String getErrorString(int errorCode) {
            switch (errorCode) {
                case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
                    return "GeoFence not available";
                case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
                    return "Too many GeoFences";
                case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
                    return "Too many pending intents";
                default:
                    return "Unknown error.";
            }
        }

 private void scheduleJob()
    {


        Bundle bundle = new Bundle();


        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(getApplicationContext()));
        Job.Builder builder = dispatcher.newJobBuilder();

        builder.setExtras(bundle);
        builder.setTag(requestId);
        builder.setService(TriggerJobService.class);
        builder.setTrigger(Trigger.executionWindow(10, 30));
        builder.setReplaceCurrent(true);
        builder.addConstraint(Constraint.DEVICE_CHARGING);
        builder.addConstraint(Constraint.ON_ANY_NETWORK);
        builder.addConstraint(Constraint.ON_UNMETERED_NETWORK);

        dispatcher.mustSchedule(builder.build());

    }

}


Это код моего TriggerJobService:

public class TriggerJobService extends JobService
{
    private static final String TAG = TriggerJobService.class.getName();

    private int count;
    @Override
    public boolean onStartJob(JobParameters job)
    {
        Log.d(TAG, "onStartJob() :: " + job.getTag());
        // Return true as there's more work to be done with this job.
        //TODO have to send request to cloud
        Bundle bundle = job.getExtras();
         callingHttpRequest();   // here is I am calling 'HTTP' request

        return true;
    }

    @Override
    public boolean onStopJob(JobParameters job)
    {
        Log.d(TAG, "onStopJob() :: " + job.getTag());
        // Return false to drop the job.
        return false;
    }

 private void callingHttpRequest() {

         HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    .readTimeout(10, TimeUnit.SECONDS)
                    .connectTimeout(10 / 2, TimeUnit.SECONDS)
                    .sslSocketFactory(sslSocketFactory().getSocketFactory())
                    .build();

        Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();

                 Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(url)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();


                API api = retrofit.create(***.class);


                Call<ResponseBody> req = api.callGeofencingTrigger(***);

                req.enqueue(new Callback<ResponseBody>() {

                    @Override
                    public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                        try {
                            String string = response.body().string();
                            Log.d (TAG, "onResponse()  :: success");

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

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        t.printStackTrace();
                       Log.d (TAG, "onFailure()  :: t : "t.getMessage());

                    }

                });

        }
}

Опять звонит то же самое. Он отлично работает и выдает правильные уведомления о триггерах, когда приложение находится в фоновом режиме или на переднем плане (вход / задержка / выход) или даже если пользователь убивает приложение из недавних задач. Также он планирует правильную работу. И вызов запроса HTTP, когда приложение находится на переднем плане, тогда оно работает нормально и печатает успех в журнале.

onResponse()  :: success

Но когда приложение уничтожается из-за недавних задач и устройство получает какой-либо триггер геозоны (вход/остановка/выход), тогда приложение планирует задание, и вызов HTTP запроса не выполняется должным образом. Это дает :

onFailure() :: t : 
</br>java.net.UnknownHostException: Unable to resolve host
"host_name": No address associated with hostname

Итак, согласно ответам @Xavier и @Stevensen, мое приложение не активирует сеть, если оно убивает из-за недавних задач. Я пробовал с firbase-JobSchedule, но все еще сталкивался с той же ошибкой, что и выше. Нужны ли приложению какие-либо специальные permission для вызова HTTP запроса, когда приложение убивает последние задачи? или есть FCM лучшие варианты для этого. Но все же есть тот же вопрос, будет ли работать FCM, даже если приложение убивает из недавних задач? FCM разбудит сеть, чтобы отправить сообщение на сервер от клиента?


person Mangesh Sambare    schedule 04.08.2017    source источник
comment
Пожалуйста, предоставьте информацию об устройстве и версии ОС.   -  person User10001    schedule 14.08.2017
comment
Пробовал на устройствах один плюс два (ОС-версия 6.0), Xiomi-Mi4i (ОС-версия 5.0.2).   -  person Mangesh Sambare    schedule 14.08.2017
comment
У вас такая же проблема на устройстве Xiaomi 5.0.2? Если это так, проблема связана не с режимом Doze (по крайней мере, на этом устройстве), так как он был добавлен в 6.0. Doze и App Standby управляют поведением всех приложений, работающих на Android 6.0 или выше developer.android.com/training/monitoring-device-state/ В любом случае, мой предыдущий совет пакетной загрузки события, если это возможно, все еще в силе.   -  person Xavier Rubio Jansana    schedule 14.08.2017
comment
Наконец моя проблема решена. Пожалуйста, посмотрите этот< /а>. Это поможет выявить проблемы.   -  person Mangesh Sambare    schedule 18.08.2017


Ответы (5)


Возможно, ваше приложение заблокировано для использования сети из-за спящего режима Android и / или режима ожидания приложения. Проверьте Оптимизация режима ожидания и Режим ожидания приложения.

Возможное решение — настроить будильник с помощью AlarmManager. Android запланирует обработку сигналов тревоги в окне обслуживания, когда вам разрешено использовать сеть.

person Stevensen    schedule 11.08.2017
comment
Я пробовал с диспетчером тревог, но все еще сталкивался с той же проблемой. Это дает мне ту же ошибку. - person Mangesh Sambare; 16.08.2017

Объяснение @Stevensen о том, что режим Doze является причиной сбоя, скорее всего, является причиной. В документации вы можете прочитать:

Следующие ограничения применяются к вашим приложениям в режиме Doze: Доступ к сети приостановлен...

Я предлагаю хранить события в БД и запланировать задание для их загрузки на сервер с помощью JobScheduler (API 21+, см. руководство здесь) или, если вам нужна поддержка старых устройств, используйте эту замену firebase -jobdispatcher (который предоставляет API, совместимый с JobScheduler, путем упаковки GCM Network Manager).

Я предлагаю установить условие необходимости сети: .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) и, возможно, .setPeriodic(long intervalMillis), чтобы ограничить количество раз, когда это происходит (например, загружать максимум один раз в час).

Пока не требуется режим реального времени, это лучший подход для экономии заряда батареи: режим Doze поможет устройству сэкономить заряд батареи, а JobScheduler позволит выполнять пакетную загрузку и просто время от времени пробуждать радиостанцию, экономя срок службы батареи. См. это краткое видео, чтобы понять суть.

person Xavier Rubio Jansana    schedule 12.08.2017
comment
Спасибо за ответ. Я попробовал firebase JobScheduler. Он отлично работает в приложении на переднем плане и в приложении в фоновом режиме. Но все еще сталкиваюсь с той же проблемой при отправке запроса, когда приложение убивает из недавней задачи и получает какой-то триггер. Он дает ‹br/› onFailure() :: t : ‹/br›java.net.UnknownHostException: невозможно разрешить хост host_name: нет адреса, связанного с именем хоста - person Mangesh Sambare; 16.08.2017
comment
Когда вы пишете "host_name", это буквально? Или это "whatever.myhost.com", и вы заменили его заполнителем, чтобы не предоставлять личную информацию? - person Xavier Rubio Jansana; 16.08.2017
comment
Ага. Я не хочу делиться своим личным доменным именем. Это как "whatever.myhost.com" - person Mangesh Sambare; 16.08.2017
comment
Хорошо, просто хотел убедиться, что это не глупая ошибка :) Не могли бы вы обновить свой код или хотя бы добавить соответствующие изменения (вызов JobScheduler и обработчик)? - person Xavier Rubio Jansana; 16.08.2017
comment
Еще одна мысль: .readTimeout(10, TimeUnit.SECONDS) и .connectTimeout(10 / 2, TimeUnit.SECONDS), возможно, слишком малы. 5 секунд (10 / 2 в connect) в некоторых случаях может быть слишком мало (возможно, радио выключено + задержка сети + ...). - person Xavier Rubio Jansana; 16.08.2017
comment
Я отредактировал свой вопрос. Пожалуйста, посмотрите на это. Хорошо для тайм-аута, я изменю от 5 до 15 секунд и дам вам знать. - person Mangesh Sambare; 16.08.2017
comment
Я посмотрел ваш код, вроде все нормально. Единственное, что может сделать его более устойчивым, — это добавить стратегию повторных попыток .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL). Но, как говорится, единственное, что сейчас приходит мне на ум, - это тайм-аут, поскольку вы уже запрашиваете выполнение задания, когда сеть доступна. Какую версию ОС вы используете для этих тестов? Все еще 6.0+? - person Xavier Rubio Jansana; 16.08.2017
comment
Я также заметил, что вы добавляете два взаимоисключающих ограничения builder.addConstraint(Constraint.ON_ANY_NETWORK);и builder.addConstraint(Constraint.ON_UNMETERED_NETWORK);. Вероятно, вам следует оставить только последний. - person Xavier Rubio Jansana; 16.08.2017
comment
Давайте продолжим обсуждение в чате. - person Mangesh Sambare; 17.08.2017
comment
Спасибо за Ваш ответ. Я решил свою проблему. См. это ответь - person Mangesh Sambare; 18.08.2017

Наконец моя проблема решена. Спасибо @Stevensen, @Xavier и одному из моих друзей, которые помогли мне определить проблему. Это связано с режимом сна.


Некоторые производители мобильных телефонов (Xiomi, Huawei и т. д.) внедрили SmartManager для оптимизации расхода заряда батареи. У них есть своего рода диспетчер батареи, который убивает приложения, а когда приложение убивает, запланированные сигналы тревоги отменяются, а также они не обнаруживают никакой активной сети или блокируют сетевой вызов из фоновой службы. Потому что производители обвиняют ненадежные приложения в энергопотреблении. Приложениям Facebook, Whats App и т. д. доверяют, и производители заносят их в белый список. Вот почему они могут вызвать сетевое событие, даже если приложение убито.


Все же я не нашел решения для этого. Так что временно я преодолеваю эту проблему для устройств Xiomi. Я защищаю свое приложение от ограничения экономии заряда батареи, чем оно работает правильно, выполняя следующие действия:

settings--> battery -> Power --> App battery saver --> your app 
Now select No restrictions( for Background settings) then Allow option for Background location 


Для версии Android M и выше приложение должно запрашивать разрешение:

Intent intent = new Intent();
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
    intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
    intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + packageName));
}
context.startActivity(intent);

и в манифесте:

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

После этого пользователь может внести ваше приложение в белый список.

person Mangesh Sambare    schedule 18.08.2017
comment
Спасибо, что поделились окончательным решением. - person Xavier Rubio Jansana; 18.08.2017

У меня была та же проблема: «java.net.UnknownHostException: невозможно разрешить хост «host_name»: нет адреса, связанного с именем хоста». Также Интернет был доступен со всеми предоставленными разрешениями Android (проверено их все даже во время выполнения).

Но решение было другим. Причина заключалась в том, что наш API-хост "host_name" (например, http://xxx.yyyy.zz) был в локальной сети и не смог из внешней сети. Та же проблема может возникнуть, если вы вызываете внешнее имя вашей компании «host_name» из локальной сети компании (это похоже на «атаку DNS Rebind» для сервера). Чтобы проверить это, вы должны попробовать открыть используемый URL-адрес в браузере, когда устройство подключено (и когда нет) к Интернету из локальной сети (например, Wi-Fi компании) и проверить правильность ответа сервера.

Проблема @Mangesh Sambare была решена, как он сказал выше, но, возможно, этот опыт будет полезен для тех, кто находится в той же ситуации, что и я.

person Irregular Expression    schedule 20.11.2018

Когда приложение переходит в фоновый режим, вам нужно время от времени его будить, чтобы определить положение мобильного телефона. Естественно, чем чаще он будет нюхать, тем быстрее и надежнее сможет обнаружить геозону. https://proximi.io/will-my-geofencing-function-in-the-background

person Uddhav Gautam    schedule 15.08.2017