IntentService перестает работать, когда приложение удаляется из последних приложений

Я использую геозону в своем приложении и на основе событий геозоны (вход или выход) я хочу выполнить какое-то действие. В документации указано, что после установки геозоны события будут запускаться автоматически, и вы сможете поймать это событие с помощью IntentService. Для этого я сделал намерение, как показано ниже:

GeofenceTransitionsIntentService.java

public class GeofenceTransitionsIntentService extends IntentService {

    Handler mHandler;
    public GeofenceTransitionsIntentService() {
        super("GeofenceTransitionsIntentService");
        mHandler = new Handler();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("JK-->>","service started!");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        Log.e("JK-->>","onHandel--->>");

        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            Log.e("JK-->>","geofenceEvent has error!");
            return;
        }

        int geofenceTransitionType = geofencingEvent.getGeofenceTransition();
        if (geofenceTransitionType == Geofence.GEOFENCE_TRANSITION_ENTER) {
            Log.e("JK-->>","enter!");
            mHandler.post(new DisplayToast(this,"Enter"));
        } else if (geofenceTransitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
            mHandler.post(new DisplayToast(this,"Exit"));
            Log.e("JK-->>","exit");
        }
    }

    public class DisplayToast implements Runnable {
        private final Context mContext;
        String mText;

        public DisplayToast(Context mContext, String text){
            this.mContext = mContext;
            mText = text;
        }

        public void run(){
            Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
        }
    }

}

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

Я пытался найти решение в Google, но в основном все ответы предлагают использовать службу, но если я не ошибаюсь, то IntentService автоматически останавливается после выполнения работы и запускается при получении любого намерения. Итак, я думаю, что более эффективно использовать IntentService для выполнения этой задачи.

ОБНОВЛЕНИЕ Я регистрирую геозону, используя следующую строку кода.

geofencingClient.addGeofences(getGeofencingRequest(),getGeofencePendingIntent());

и в getGeofencePendingIntent() я запускаю службу намерений, используя следующую строку кода.

private PendingIntent getGeofencePendingIntent() {
        if(geofencePendingIntent != null)
            return geofencePendingIntent;
        Intent in = new Intent(SetProfileOnlineActivity.this,GeofenceTransitionsIntentService.class);
        geofencePendingIntent = PendingIntent.getService(SetProfileOnlineActivity.this,111451,in,PendingIntent.FLAG_UPDATE_CURRENT);
        return geofencePendingIntent;
    }

person Jaydip Kalkani    schedule 02.03.2018    source источник
comment
Как вы начинаете это IntentService. IntentService не будет жить вечно, выполнив свою задачу, он остановится. Вы можете взглянуть на IntentService Документацию.   -  person ADM    schedule 02.03.2018
comment
Только служба может работать в фоновом режиме неограниченное время без запуска приложения. Даже если приложение остановлено, служба не остановится. Но IntentService остановится, как только задача будет выполнена, или если новых задач не будет.   -  person Akshay    schedule 02.03.2018
comment
посмотрите на обновленный вопрос, чтобы увидеть, как я запускаю IntentService. @АДМ   -  person Jaydip Kalkani    schedule 02.03.2018
comment
Поскольку в этом ответе говорится, что IntentService будет остановлен после выполнения задачи, но запустится снова, когда будет получено какое-либо намерение. @акшай   -  person Jaydip Kalkani    schedule 02.03.2018
comment
У вас есть контекст передачи, поскольку SetProfileOnlineActivity.this это действие, не так ли? Так как же этот контекст будет жить в фоновом режиме? Я что-то пропустил здесь?   -  person ADM    schedule 02.03.2018
comment
Да, это деятельность. извините за этот вопрос, но, пожалуйста, скажите мне, что я должен передать вместо «SetProfileOnlineActivity.this» @ADM   -  person Jaydip Kalkani    schedule 02.03.2018
comment
Ну, я не очень хорошо знаком с Geofence. Я просмотрел документацию. И ваш код выглядит так же. Так что продолжайте копать. Проверьте это и на других устройствах. на другом уровне API, чтобы убедиться.   -  person ADM    schedule 02.03.2018
comment
Да, это начнется после получения намерения, но если ваше приложение вообще не работает, как вы можете отправить намерение в IntentService() @ Jaydip Kalkani   -  person Akshay    schedule 02.03.2018
comment
Нельзя ли отправить намерение из внешнего приложения, изменив контекст (SetprofileActivity.this)?? Если это невозможно, скажите, пожалуйста, что мне делать, чтобы выполнить мою задачу. @akshay   -  person Jaydip Kalkani    schedule 02.03.2018
comment
Я не понял вас, указав внешнее приложение. Используйте этот пример stackoverflow.com/a/28535885/7156233, чтобы получать обновления местоположения. Используйте IntentService для GeoFencing, в случае вызова события locationChnage служба IntentService будет работать неопределенное время в фоновом режиме и получать locationUpdates.   -  person Akshay    schedule 02.03.2018
comment
Из внешнего приложения я имею в виду, когда приложение закрыто из последнего приложения. Позвольте мне попробовать решение, которое вы мне дали. Спасибо за решение. @акшай   -  person Jaydip Kalkani    schedule 02.03.2018
comment
У вас нет никакого контроля над пользователем. Пользователь может закрыть приложение в любое время. Используйте службу с START_REDELIVER_INTENT, она перезапустит службу, даже если она остановлена ​​системой из-за выделения памяти или ресурсов.   -  person Akshay    schedule 02.03.2018
comment
Спасибо за предложение протестировать приложение на разных API. Из этого я вижу, что мое приложение отлично работает со всеми API-интерфейсами Android, кроме Oreo. До сих пор я тестировал свое приложение на Android Oreo. он не работает в фоновом режиме в oreo, потому что в android oreo реализована более эффективная логика сохранения, как указано в документации. Итак, моя проблема решена. еще раз спасибо. @АДМ   -  person Jaydip Kalkani    schedule 02.03.2018
comment
Ты понял, приятель.. Сайонара.   -  person ADM    schedule 02.03.2018


Ответы (3)


Эта служба будет работать всегда:


Перейти к проекту java -> щелкните правой кнопкой мыши -> Новый-> сервис-> назовите службу сторожем


сторож.java

public class watchman extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";


public watchman() { }

@Override
public void onCreate()
{

    try
    {
        mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);

        mBuilder = new NotificationCompat.Builder(this, null);
        mBuilder.setContentTitle("Insta Promo")
                .setContentText("We are ready to help you.")
                .setSmallIcon(R.drawable.ic_launcher_background);



        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);

            // Configure the notification channel.
            notificationChannel.setDescription("Channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableVibration(true);
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            mNotifyManager.createNotificationChannel(notificationChannel);
        }
        else
        {
            mBuilder.setContentTitle("Insta Promo")
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setColor(ContextCompat.getColor(this, R.color.colorAccent))
                    .setVibrate(new long[]{100, 250})
                    .setLights(Color.YELLOW, 500, 5000)
                    .setAutoCancel(true);
        }

        mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);

        mNotifyManager.notify(1, mBuilder.build());

        startForeground(1, mBuilder.build());

    }
    catch(Exception e)
    {
        Log.d(TAG, "EXCEPTION IN SHOWING NOTIFICATION xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...\n");
        Log.e("MY_APP", "exception", e);

    }

}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{

    new Thread(new Runnable()
    {

        public void run()
        {

            while (true)
            {
                try
                {
                    Log.d(TAG, "Thread : Running again...\n");

                    Thread.sleep(10000);
                }
                catch (InterruptedException e)
                {
                    Log.d(TAG, "Thread : InterruptedException Error in service...\n");
                }

            }


        }

    }).start();
    return START_STICKY;

}

@Override
public void onDestroy()
{
    super.onDestroy();
}

@Override
public IBinder onBind(Intent intent)
{
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

}

Он будет автоматически зарегистрирован в файле манифеста, поскольку вы создали его как службу, нет необходимости обновлять файл манифеста.


Из основного действия или из любого места, где вы хотите его запустить, назовите его как

    Log.d(TAG, " Good to Go \n");
    Log.d(TAG, "Starting Service from main...\n");
    Intent intent = new Intent(MainActivity.this, watchman.class);
    startService(intent);
    Log.d(TAG, "Main has started the service...\n");

Теперь, даже если вы удалили его из недавних..., он всегда будет работать в памяти для вас, чтобы проверить его, следите за logcat. Надеюсь, поможет. Он работает в проекте с версии 4.1 и выше до последней версии 8.0 oreo.


для показа уведомлений я использую разрешение на вибрацию, поэтому также делаю файл манифеста доступным для вас.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rushi.oreo">


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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service
        android:name=".watchman"
        android:enabled="true"
        android:exported="true" />


</application>

</manifest>

Надеюсь, это действительно поможет вам или кому-то еще.

person Community    schedule 02.03.2018
comment
Если вы хотите, чтобы эта постоянно работающая служба работала в фоновом режиме, не открывая приложение при каждом ребботе или запуске, вам потребуется только класс получателя и манифест обновления для получения при завершении загрузки. Если вы тоже этого хотите, дайте мне знать здесь. - person ; 02.03.2018
comment
Также дайте мне знать, что происходит, когда вы используете это, я буду направлять вас, пока он не будет работать так, как вы предполагали. На самом деле это рабочий код, и он должен работать. Но дайте мне знать, чтобы я мог помочь - person ; 02.03.2018
comment
Я рекомендую создать новый пустой проект с пустой активностью и использовать эти инструкции, чтобы заставить его работать. Как только вы заработаете, ваша идея станет ясной, и вы сможете реализовать ее в своем проекте в соответствии с вашими потребностями. - person ; 02.03.2018

  1. IntentService автоматически остановится, когда назначенная ему работа будет завершена.
  2. Если вы хотите, чтобы служба работала в фоновом режиме с минимальными шансами на остановку, она должна быть службой переднего плана. Обязательно запустите службу в фоновом рабочем потоке, потому что по умолчанию служба работает в основном потоке.

Подробнее здесь: https://developer.android.com/reference/android/app/Service.html#startForeground(int,%20android.app.Notification)

Но обратите внимание на то, что выделение службы на передний план слишком сильно влияет на срок службы батареи вашего телефона. И создание Службы в качестве переднего плана также раздражает пользователя, поскольку она всегда показывает уведомление и не может быть закрыта.

Вы можете лучше использовать JobScheduler или Firebase JobDispatcher для планирования фоновых работ.

person Asutosh Panda    schedule 02.03.2018

Я нашел ответ... в моем коде не было проблем, и IntentService тоже работал отлично, но ошибка была в тестировании. Я тестировал свое приложение на работающем устройстве Android Oreo.

В Android Oreo Google обновил свою политику, согласно которой на переднем плане они будут отправлять обновления местоположения любое количество раз, но в фоновом режиме они будут отправлять обновления местоположения только несколько раз в час. Основная причина этого - сохранить лучшую жизнь устройства.

Для получения дополнительной информации об обновлениях местоположения Android Oreo вы можете проверить эту документация.

person Jaydip Kalkani    schedule 03.03.2018