Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android 13 Bad notification for startForeground

Each time I execute my app I obtain a "Bad notification for startForeground" error

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.pennskanvtic, PID: 17447
    android.app.RemoteServiceException$CannotPostForegroundServiceNotificationException:
Bad notification for startForeground
        at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:1978)
        at android.app.ActivityThread.-$$Nest$mthrowRemoteServiceException(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2237)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7884)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)`

My service only start a timer and display notification (I try with setChannelId inside NotificationCompat.Builder without any change) :

public class MyService extends Service {

    private int i_NotifID = 1336;
    private String CHANNEL_ID = "MyServiceChannel";


    private CountDownTimer mCptRebours;
    private Notification notification;
    private NotificationCompat.Builder builder;
    private NotificationManagerCompat notificationManager;

    private long l_TimerTime_ms;

    private MainActivity mainActivity;

    @Override
    public void onCreate() {

        super.onCreate();

        //Resources res = this.getResources();

        builder = new NotificationCompat.Builder(this, CHANNEL_ID);
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentTitle("PennSkanvTic...Tac...");
        builder.setContentText("waiting for start...");
        //builder.setChannelId(CHANNEL_ID);
        //builder.setOngoing(true);
        //builder.setPriority(Notification.PRIORITY_HIGH);

        notificationManager = NotificationManagerCompat.from(this);
        //notificationManager.notify(i_NotifID, builder.build());

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

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

        l_TimerTime_ms = intent.getLongExtra("l_TimerTime_ms", 55000);
        builder.setContentText(Long.toString(l_TimerTime_ms / 1000));

        mainActivity = MainActivity.getMainActivity();

        startForeground(i_NotifID, builder.build());
        startTimer();

        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {

        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    private void startTimer() {

        mCptRebours = new CountDownTimer(l_TimerTime_ms, 1000) {
            @Override
            public void onTick(long l_RemainingTime_ms) {

                // Update notification content
                builder.setContentText(Long.toString(l_RemainingTime_ms / 1000));
                notificationManager.notify(i_NotifID, builder.build());

                // Update frontend (MainActivity value)
                mainActivity.UpdateFrontend(l_RemainingTime_ms);
            }

            @Override
            public void onFinish() {

                //Log.d("MonApplication", "MyForegroundService onFinish");
            }
        }.start();
    }
}

My MainActivity ask for permission inside onStart() :

        String[] permissionArray = {Manifest.permission.FOREGROUND_SERVICE, Manifest.permission.VIBRATE, Manifest.permission.POST_NOTIFICATIONS};
        ActivityCompat.requestPermissions(this, permissionArray, 0);

and start the service :

        Intent serviceIntent = new Intent(MainActivity.this, MyService.class);
        serviceIntent.putExtra("l_TimerTime_ms", mValCompteReboursConfig);
        ContextCompat.startForegroundService(MainActivity.this, serviceIntent);`

My AndroidManifest.xml declare the service and permission :

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

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

And I ask for a SDK version 33 on my build.gradle file :

   defaultConfig {
        applicationId "com.example.pennskanvtic"
        minSdk 21
        targetSdk 33
        compileSdk 33
        targetSdkVersion 33
        compileSdkVersion 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

It is all what I find to try. I have now no idea why I still have an error when launching my foreground service.

like image 341
geo667 Avatar asked Mar 03 '26 11:03

geo667


2 Answers

Finally find the problem : I forget to create notification channel... This code added solve my problem :

NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "PennSkanvTicChannel", NotificationManager.IMPORTANCE_MAX);
channel.setDescription("PennSkanvTic channel for foreground service notification");

notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);

Then, the same CHANNEL_ID need to be use when creating notification (NotificationCompat.Builder).

Hope this help somebody.

like image 67
geo667 Avatar answered Mar 04 '26 23:03

geo667


I also met the issue today, for me the cause is the context which transferred to the NotificationCompat.Builder is the application instead of the context of service. After I changed the context to that of service, the issue disappears. Note it here in case someone need it.

Reproduce code:

val notification = NotificationCompat.Builder(application, CHANNEL_ID).build()

Solution:

val notification = NotificationCompat.Builder(service, CHANNEL_ID).build()

Full NotificationUtils:

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import androidx.core.app.NotificationCompat

object NotificationUtils {
    const val CHANNEL_ID = "MyForegroundServiceChannel"
    const val CHANNEL_NAME = "Channel name"
    const val NOTIFICATION_ID = 1

    fun createNotificationChannel() {
        val notificationChannel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT)
        val notificationManager = MyApplication.context.getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(notificationChannel)
    }

    fun startForeground(service: Service) {
        val notification = NotificationCompat.Builder(service, CHANNEL_ID).build()
        service.startForeground(NOTIFICATION_ID, notification)
    }
}
like image 29
Kevin Avatar answered Mar 04 '26 23:03

Kevin