Search code examples
javaandroid-notificationsandroid-13

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.


Solution

  • 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.