IntentService stops working when app is removed from recent apps

南楼画角 提交于 2020-01-14 06:49:29

问题


I am using geofence in my app and based on geofence events (Enter or Exit) I want to perform some action. Geofence documentation says that once you set geofence it will trigger events automatically and you can catch this events with IntentService. For that I have made intentservice as below:

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

}

Now, problem is that when app is open(No matter foreground or background) and I enter or exit in geofence it works fine and show me a toast message and logcat shows log but when I remove app from recent apps there is no toast message showing to me or no log is showing in logcat.

I have tried to find solution on google but mostly all answers suggests to use the service but if i am not wrong then IntentService stops itself automatically after work is done and start itself when any intent received. So, I think it's more efficient to use IntentService to do this task.

UPDATE I am registering geofence using following line of code.

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

and in getGeofencePendingIntent() i am starting intent service using following line of code.

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

回答1:


This Service will run always :


Goto project java -> right click->New->service->service name it watchman


watchman.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");
}

}

It will get automatically registered in manifest file as you created it as service, no need to update manifest file.


From main activity or from wherever you want to start it call it like

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

Now you even if removed it from recents..., It will be there in memory running always for you, To check it keep eye on logcat. Hope it helps. Its working in project from 4.1 onwards upto latest 8.0 oreo


for showing notifications i am using vibration permission so also making manifest file available for you.

<?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>

Hope it really helps you or someone else.




回答2:


  1. IntentService will stop automatically when the work assigned to it is finished.
  2. If you want a service to run in background with very less chances of getting stopped, it has to be a Foreground Service. Please make sure to start your Service in a background worker thread because by default a Service runs on the main thread.

More details are here - https://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)

But please note that making a Service as foreground impacts your phone's battery life too much. And a making a Service as Foreground is also annoying to the user since it shows a notification always and cannot be closed.

You can better use a JobScheduler or Firebase JobDispatcher to schedule background works.




回答3:


I had found an answer... there was no problem in my code and IntentService was also working perfectly but the mistake was in the testing. I was testing my application on android Oreo running device.

In android oreo google has updated their policy that in foreground they will send location updates any number of times but in background they will send location updates only few times in hour. The main reason behind it to save the bettery life of device.

For more information about android oreo location updates you can check out this documentation.



来源:https://stackoverflow.com/questions/49063314/intentservice-stops-working-when-app-is-removed-from-recent-apps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!