FOREGROUND_SERVICE_TYPE getting lost when starting my foreground service

288 views Asked by At

I have an app that requires capturing location information in a foreground service. It has been working until I raised my SDK versions to API 34 based on other needs. I understand there are new requirements for foreground services in API 34 and have done my best to follow the recommended changes. From testing, the parameters getting passed in ForegroundLocationService.class statement

     ServiceCompat.startForeground(this, 100, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); 

is lost when it goes through SystemForegroundService.class and causes the error as follows:

FATAL EXCEPTION: main
                                                                                                    Process: com.grgmobilesolutions.peepsconnection, PID: 18488
                                                                                                    android.app.InvalidForegroundServiceTypeException: Starting FGS with type none callerApp=ProcessRecord{ed24bae 18488:com.grgmobilesolutions.peepsconnection/u0a190} targetSDK=34 has been prohibited
                                                                                                        at android.app.InvalidForegroundServiceTypeException$1.createFromParcel(InvalidForegroundServiceTypeException.java:53)
                                                                                                        at android.app.InvalidForegroundServiceTypeException$1.createFromParcel(InvalidForegroundServiceTypeException.java:49)
                                                                                                        at android.os.Parcel.readParcelableInternal(Parcel.java:4870)
                                                                                                        at android.os.Parcel.readParcelable(Parcel.java:4852)
                                                                                                        at android.os.Parcel.createExceptionOrNull(Parcel.java:3052)
                                                                                                        at android.os.Parcel.createException(Parcel.java:3041)
                                                                                                        at android.os.Parcel.readException(Parcel.java:3024)
                                                                                                        at android.os.Parcel.readException(Parcel.java:2966)
                                                                                                        at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6761)
                                                                                                        at android.app.Service.startForeground(Service.java:862)
                                                                                                        at androidx.work.impl.foreground.SystemForegroundService$Api29Impl.startForeground(SystemForegroundService.java:173)
                                                                                                        at androidx.work.impl.foreground.SystemForegroundService$1.run(SystemForegroundService.java:127)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:958)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:205)
                                                                                                        at android.os.Looper.loop(Looper.java:294)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:8177)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

The following is my manifest items for permissions and the services



<service
            android:name="ForegroundLocationService"
            android:foregroundServiceType="location"
            android:enabled="true"
            android:exported="true">

        </service>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

The following is my ForegroundLocationService.class

package com.grgmobilesolutions.peepsconnection;

import static android.content.ContentValues.TAG;

import android.Manifest;
import android.app.Service;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.ServiceCompat;
import androidx.core.content.ContextCompat;

import com.bugfender.sdk.Bugfender;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.function.Consumer;


public class ForegroundLocationService  extends Service {


    public static final String CHANNEL_ID = "ForegroundServiceChannel";
    public PendingIntent pendingIntent;
    public Context context;
    public BroadcastReceiver receiver;
    public IntentFilter intentFilter;
    @Override
        public void onCreate() {

        super.onCreate();
        context = getApplicationContext();
        //Log.i(TAG, "LocationWorkManager ForegroundLocationService appLifecycleEvent onCreate: ");
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            //Log.i(TAG, "LocationWorkManager " + Thread.currentThread().getId() + " ForegroundLocationService appLifecycleEvent onStartCommand: ");
            context = getApplicationContext();
            String input = "PeepsConnection is capturing current location if you have an open check in";
            createNotificationChannel();
            Intent notificationIntent = new Intent(this, Login.class);

            // this is to verify permissions take out after testing
            boolean permissionGrantedStatus = (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
            if (!permissionGrantedStatus) {
                Bugfender.e(TAG, "ForegroundLocationService onStartCommand: ACCESS_FINE_LOCATION= " + permissionGrantedStatus);
            }
            permissionGrantedStatus = (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED);
            if (!permissionGrantedStatus) {
                Bugfender.e(TAG, "ForegroundLocationService onStartCommand: ACCESS_COARSE_LOCATION= " + permissionGrantedStatus);
            }
            permissionGrantedStatus = (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE) == PackageManager.PERMISSION_GRANTED);
            if (!permissionGrantedStatus) {
                Bugfender.e(TAG, "ForegroundLocationService onStartCommand: FOREGROUND_SERVICE_CONNECSTED_DEVICE= " + permissionGrantedStatus);
            }
            permissionGrantedStatus = (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED);
            if (!permissionGrantedStatus) {
                Bugfender.e(TAG, "ForegroundLocationService onStartCommand: ACCESS_BACKGROUND_LOCATION= " + permissionGrantedStatus);
            }
            permissionGrantedStatus = (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.FOREGROUND_SERVICE) == PackageManager.PERMISSION_GRANTED);
            if (!permissionGrantedStatus) {
                Bugfender.e(TAG, "ForegroundLocationService onStartCommand: FOREGROUND_SERVICE= " + permissionGrantedStatus);
            }
            permissionGrantedStatus = (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.FOREGROUND_SERVICE_LOCATION) == PackageManager.PERMISSION_GRANTED);
            if (!permissionGrantedStatus) {
                Bugfender.e(TAG, "ForegroundLocationService onStartCommand: FOREGROUND_SERVICE_LOCATION= " + permissionGrantedStatus);
            }
            // through here

            if (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
                    (ContextCompat.checkSelfPermission(context,
                            Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
                            (ContextCompat.checkSelfPermission(context,
                                    Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE) == PackageManager.PERMISSION_GRANTED &&
                            (ContextCompat.checkSelfPermission(context,
                                    Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED &&
                                    (ContextCompat.checkSelfPermission(context,
                                            Manifest.permission.FOREGROUND_SERVICE) == PackageManager.PERMISSION_GRANTED &&
                                            (ContextCompat.checkSelfPermission(context,
                                                    Manifest.permission.FOREGROUND_SERVICE_LOCATION) == PackageManager.PERMISSION_GRANTED)))))) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent,
                            PendingIntent.FLAG_IMMUTABLE);
                } else {
                    pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent,
                            PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
                }

                Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                        .setContentTitle("Location Service Running")
                        .setContentText(input)
                        .setSmallIcon(R.drawable.map_marker_down)
                        .setContentIntent(pendingIntent)
                        .build();
                ServiceCompat.startForeground(this, 100, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
            }
            return START_STICKY;
        }
        @Override
        public void onDestroy() {
            super.onDestroy();

        }
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        private void createNotificationChannel() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel serviceChannel = new NotificationChannel(
                        CHANNEL_ID,
                        "Foreground Service Channel",
                        NotificationManager.IMPORTANCE_DEFAULT
                );
                NotificationManager manager = getSystemService(NotificationManager.class);
                manager.createNotificationChannel(serviceChannel);
            }
        }
    }

When the app runs the method startForeground() in SystemForegroundService.class, this code is passed the parameters (1,0,Notification). I have not been able to track it backwards to see where it is lost.

public void startForeground(
            final int notificationId,
            final int notificationType,
            @NonNull final Notification notification) {

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    Api29Impl.startForeground(SystemForegroundService.this, notificationId,
                            notification, notificationType);
                } else {
                    startForeground(notificationId, notification);
                }
            }

Attached is my build.gradle in case it a version issue.

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
    compileSdkVersion 34
    defaultConfig {
        applicationId "com.grgmobilesolutions.peepsconnection"
        minSdkVersion 34
        targetSdkVersion 34
        versionCode 2
        versionName "Beta 2.0.1"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        customDebugType {
            debuggable true
        }
    }
    compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }
    namespace 'com.grgmobilesolutions.peepsconnection'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation 'androidx.core:core:1.12.0'
    implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'

    def work_version = "2.5.0"

    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"
    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"

    // optional - Multiprocess support

    implementation 'com.bugfender.sdk:android:3.+'

    implementation 'com.google.firebase:firebase-appcheck-debug:17.1.1'
    implementation 'com.google.firebase:firebase-appcheck-playintegrity:17.1.1'
    implementation 'com.android.billingclient:billing:6.1.0'
    implementation "androidx.work:work-multiprocess:$work_version"
    implementation group: 'org.locationtech.jts', name: 'jts-core', version: '1.15.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.navigation:navigation-fragment:2.4.2'
    implementation 'androidx.navigation:navigation-ui:2.4.2'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.recyclerview:recyclerview:1.2.1'
    implementation 'com.google.android.gms:play-services-ads:22.5.0'
    implementation 'com.google.firebase:firebase-ads:22.5.0'
    implementation 'androidx.work:work-runtime:2.8.0-alpha02'
    implementation 'androidx.preference:preference:1.2.0'
    implementation 'com.google.android.gms:play-services-maps:18.2.0'
    implementation 'com.google.firebase:firebase-auth:22.3.0'
    implementation 'androidx.annotation:annotation:1.3.0'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
    implementation 'com.google.firebase:firebase-database:20.3.0'
    implementation 'com.google.firebase:firebase-functions:20.4.0'
    implementation 'androidx.wear:wear:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    implementation "androidx.viewpager2:viewpager2:1.0.0"
    implementation "com.github.MikeOrtiz:TouchImageView:1.4.1" // last SupportLib version
    implementation platform('com.google.firebase:firebase-bom:30.4.1')
    implementation 'com.google.firebase:firebase-analytics:21.5.0'
    implementation 'com.google.firebase:firebase-messaging:23.3.1'
    implementation 'com.google.firebase:firebase-appcheck-playintegrity'
    implementation 'com.firebaseui:firebase-ui-database:3.2.1'
    implementation 'com.firebaseui:firebase-ui-auth:6.4.0'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'com.google.android.gms:play-services-gcm:17.0.0'
    implementation 'com.android.volley:volley:1.2.1'
    implementation 'com.google.android.gms:play-services-location:20.0.0'
    implementation 'com.android.support:multidex:1.0.3'
    implementation 'com.google.android.libraries.maps:maps:3.1.0-beta'
    implementation 'androidx.biometric:biometric:1.2.0-alpha04'

    implementation 'com.google.auto.value:auto-value-annotations:1.6.5'
    implementation 'com.google.maps.android:android-maps-utils:2.4.0'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'com.androidmapsextensions:android-maps-extensions:2.4.0'
    implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'

    implementation('com.mikepenz:materialdrawer:5.9.5@aar') {
        transitive = true
        exclude group: 'com.android.support'
    }
    implementation files('libs/activation.jar')
    implementation files('libs/additionnal.jar')
    implementation files('libs/mail.jar')

    // Room components
    implementation "androidx.room:room-runtime:2.6.1"
    annotationProcessor "androidx.room:room-compiler:2.6.1"
    androidTestImplementation "androidx.room:room-testing:2.6.1"

    implementation 'androidx.sqlite:sqlite:2.4.0'
    //implementation "net.zetetic:android-database-sqlcipher:4.5.3"
    implementation 'net.zetetic:sqlcipher-android:4.5.5@aar'
    // Lifecycle components
    implementation "androidx.lifecycle:lifecycle-extensions:$rootProject.archLifecycleVersion"
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$rootProject.archLifecycleVersion"

    // UI
    implementation "com.google.android.material:material:1.3.0"

    // Testing
    androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
    compileOnly 'com.google.android.wearable:wearable:2.8.1'
}
0

There are 0 answers