Search code examples
androidandroid-serviceandroid-locationandroid-broadcastreceiver

My service works with android 7.1.1 but not with android 9


My app uses a background service to listen to GPS position changes. It works on android 7.1.1 (even if my activity is closed or the screen is turn off). When I tried it on android 9 (with the AVD) it only works when the activity is in the foreground, otherwise not. It looks like the service is stopped when the app is closed. minSdkVersion is set to 23. Why app have different behavior on different API? Android does not guarantee the compatibility of apps on newer OS versions?

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**code to request permission*/

        startService(new Intent(this, EventControllerService.class));

    }
}

public final class EventControllerService extends Service {
    private final static int MIN_TIME_FOR_GPS_UPDATES = 1;
    private final static float MIN_METER_FOR_GPS_UPDATES = 10.0f;
    private static NotificationManager mNotificationManager;
    private final BroadcastReceiver receiverDNDChange = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //work on receive
        }
    };
    private final EventControllerService self = this;
    private final LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {            
            Toast.makeText(self, "DENTRO", Toast.LENGTH_LONG).show();
            try {
                //work to do on position change
            } catch (SecurityException ignored) {                
                stopSelf();
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();        
        try {
            mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            IntentFilter filter = new IntentFilter();
            filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
            registerReceiver(receiverDNDChange, filter);

            LocationManager mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_FOR_GPS_UPDATES, MIN_METER_FOR_GPS_UPDATES, locationListener);
        } catch (SecurityException ignored) {           
            stopSelf();
        }
    }

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

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

    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />


    <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"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        <service android:name=".EventControllerService"/>
        <receiver android:name="marcomantovani.pcd.silentmap.AutoStart">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

How can I change code to avoid this problem?


Solution

  • I understand you read this: https://developer.android.com/about/versions/oreo/background

    There are many changes related to background services and especially GPS in Android 9. Note this also (so targeting API23 is not a solution):

    By default, these changes only affect apps that target Android 8.0 (API level 26) or higher. However, users can enable these restrictions for any app from the Settings screen, even if the app targets an API level lower than 26. You may need to update your app to comply with the new limitations.

    What you can do right now and how we make it work in our apps. Migrate your service to compatible with Android 9. I suggest using:

    startForegroundService()

    Make your service to run on foreground. It's a small change. Just change one flag nad start your service this way.

    Show notification that your app is working (this will keep your app working even when user is leaving the app otherwise - Android OS will limit your service)

    Targeting API23 is a bad idea also because of this:

    Starting August 1, 2019, Google Play requires that new apps target at least Android 9.0 (API level 28), and that app updates target Android 9.0 from November 1, 2019. Until these dates, new apps and app updates must target at least Android 8.0 (API level 26).

    TL;DR 1. Migrate service to foreground 2. Create simple notification that will tell your user that app is working 3. Start service with startForeground()