1

I know that there are a lot of questions and answers out there regarding this topic but despite this I am not able to implement a never ending task which is running on an Android 7.0 device. It is working perfectly on emulator (using API level 24) but not on a real device (Xiaomi Redmi Note 4, Android 7.0 NRD90M). On emulator for instance when I close the application then the LocationUpdateService.onDestroy and the AutoStartLocationUpdate.onReceive methods are called properly as expected. But on the real device are not.

Or should I use some other approach like Alarm Manager instead?

Would someone please give me some hints? Thanks

Here is my implementation:

The Service:

package com.ivan.archangel;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.util.Timer;
import java.util.TimerTask;

public class LocationUpdateService extends Service {

    private Timer timer;

    @Override
    public void onCreate() {
        super.onCreate();
        timer = new Timer();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Log.i("Ivan", "tick");
            }

        }, 0, 1000);
        Log.i("Ivan", "Timer started");
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        timer.cancel();
        Log.i("Ivan", "Timer stopped");

        Intent broadcastIntent = new Intent("Hahaha");
        getApplicationContext().sendBroadcast(broadcastIntent);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

The BroadcastReceiver

package com.ivan.archangel;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class AutoStartLocationUpdate extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("Ivan", "Restarting LocationUpdateService...");
        context.startService(new Intent(context, LocationUpdateService.class));
        Log.i("Ivan", "Restarted LocationUpdateService");
    }

}

The manifest:

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />

    <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=".Home"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <meta-data
            android:name="com.facebook.sdk.ApplicationId"
            android:value="@string/facebook_app_id" />

        <activity
            android:name="com.facebook.FacebookActivity"
            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
            android:label="@string/app_name" />
        <activity
            android:name="com.facebook.CustomTabActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="@string/fb_login_protocol_scheme" />
            </intent-filter>
        </activity>

        <service
            android:name=".LocationUpdateService"
            android:enabled="true"
            android:stopWithTask="false"/>

        <receiver
            android:name=".AutoStartLocationUpdate"
            android:enabled="true"
            android:exported="true"
            android:label="RestartServiceWhenStopped">
            <intent-filter>
                <action android:name="Hahaha" />
                <!--<action android:name="android.intent.action.BOOT_COMPLETED" />-->
            </intent-filter>
        </receiver>
        <receiver
            android:name=".SMSReceiver"
            android:exported="true"
            android:permission="android.permission.BROADCAST_SMS">
            <intent-filter android:priority="5822">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
        <!--
             The API key for Google Maps-based APIs is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps"></activity>
    </application>

</manifest>
Iván
  • 31
  • 1
  • 6
  • 1
    MIUI has extremely aggressive memory management. As soon as an app is closed from Recents, by default MIUI will force kill it, bypassing the normal `onDestroy()` lifecycle methods. Make sure you whitelist your app from battery optimizations – TheWanderer Oct 19 '18 at 12:28
  • Thanks for the answer. I tried to whitelist it under Options/Batter Saver/No restrictions but it didn't help. onDestroy is never called. – Iván Oct 19 '18 at 14:04

1 Answers1

2

You can also implement Forground Service by calling startForeground() in onStartCommand of your Service class

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


    // your code

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
        .setContentTitle("Print Server running..")
        .setContentText("")
        .setTicker("")
        .setContentIntent(pendingIntent);
    Notification notification = builder.build();
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (notificationManager != null) {
                notificationManager.createNotificationChannel(channel);
            }
    }
    startForeground(Integer.parseInt(NOTIFICATION_CHANNEL_ID), notification);.
} 

Links

Service Limitation DOC

Google Developer Link

Foreground Service Implementation

  • 1
    Android 7 (API level 24) doesn't support startForeground. – Iván Oct 19 '18 at 14:05
  • 1
    Note to reviewers: the Very Low Quality queue isn't for determining the correctness of an answer - that's what comments and voting are for. I'm voting "looks OK" on this because it's an actual attempt to answer the question. – EJoshuaS - Stand with Ukraine Oct 19 '18 at 16:02
  • 1
    @Iván [`startForeground()`](https://developer.android.com/reference/android/app/Service.html#startForeground(int,%20android.app.Notification)) has been available since API level 5. – greeble31 Oct 19 '18 at 18:25
  • @Iván As per my knowledge startForeground() will face issue from SDK 26 and above. Check updated answer. – XtremePlayer Oct 20 '18 at 06:35
  • Android studio says: "Call re quires API level 26 (current min is 24) android.content.ContextWrapper#startForegroundService" – Iván Oct 20 '18 at 16:11
  • @Iván are we talking about `startForeground()`, or `startForegroundService()`? All you need is `startForeground()`. – greeble31 Oct 20 '18 at 20:21
  • @Iván `startForegroundService()` is introduced in `Android O`. We are talking about `startForeground()`. Please refer the DOC for more :) – XtremePlayer Oct 21 '18 at 15:08
  • OK. Sorry I misunderstood. However startForeground doesn't work either. The service is running while the app is running but after closing it the service dose nothing (there is no more "thick" in the log. – Iván Oct 21 '18 at 19:51
  • @Ivan I think what @xtreme-player is saying is that you should ditch the whole `sendBroadcast()`/"Hahaha" in `onDestroy()` approach. That is a very non-standard way of trying to keep a Service running, and unlikely to work. Instead, just keep it running by making it a foreground service. Then, you can run a `CountDownTimer`, repeatedly, with a 1000ms interval, to do your processing. The system is unlikely to interfere with you, that way. – greeble31 Oct 22 '18 at 16:13
  • Thanks @greeble31. I have already tried the foreground approach but it does not work either after closing the application :( I have created a GitHub repo for the solution. This commit uses the foreground solution without broadcast: https://github.com/zahorans/android-service/tree/d20d9e8358f9261e7823e8c71d5815f41de1d887 – Iván Oct 22 '18 at 20:03
  • The latest version in the repo (https://github.com/zahorans/android-service) is using CountDownTimer. Still isn't running after the app is closed. – Iván Oct 23 '18 at 07:08
  • Hi @Iván, were you able to find a way for running a never ending service? If so, can you share the details please, as I am working on something similar. Thanks – DS009 Jul 09 '20 at 17:29
  • Hi, I didn't continue playing with it. It must be a Xiaomi problem. – Iván Jul 12 '20 at 13:27