Skip to content

Instantly share code, notes, and snippets.

@aslamanver
Last active December 15, 2023 00:23
Show Gist options
  • Save aslamanver/f32a0bb8461c250d4a945e11f6771456 to your computer and use it in GitHub Desktop.
Save aslamanver/f32a0bb8461c250d4a945e11f6771456 to your computer and use it in GitHub Desktop.
Android foreground service with notification alert

Start the service

ContextCompat.startForegroundService(this, new Intent(this, MyForegroundService.class));

Permissions

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

Manifest

<service
    android:name=".MyForegroundService"
    android:icon="@drawable/ic_notification"
    android:foregroundServiceType="location"
    android:label="MFS" />

User accept permissions (Example)

if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 2000);
    }
}
package com;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
public abstract class BaseForegroundServiceJava extends Service {
protected final IBinder mBinder = new LocalBinder();
protected int REQUEST_CODE, NOTIFICATION_ID = 3000;
protected String CHANNEL_ID = "ForegroundService_ID";
protected String CHANNEL_NAME = "ForegroundService Channel";
protected NotificationManager mNotificationManager;
protected NotificationCompat.Builder mNotificationBuilder;
public static void start(Context context, Class<? extends BaseForegroundServiceJava> serviceClass) {
ContextCompat.startForegroundService(context, new Intent(context, serviceClass));
}
public static void stop(Context context, Class<? extends BaseForegroundServiceJava> serviceClass) {
context.stopService(new Intent(context, serviceClass));
}
protected abstract Notification serviceNotification();
@Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
Notification notification = serviceNotification();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(
NOTIFICATION_ID,
notification,
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ? ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION : 0);
} else {
startForeground(NOTIFICATION_ID, notification);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
protected Notification createNotification(String title, String message, int smallIcon, int bigIcon, Class<?> intentClass) {
// Get the layouts to use in the custom notification
// RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.notification_main);
// notificationLayout.setTextViewText(R.id.txtTitle, message);
// .setCustomBigContentView(notificationLayout);
mNotificationBuilder.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true);
if (smallIcon != 0) {
mNotificationBuilder.setSmallIcon(smallIcon);
}
if (bigIcon != 0) {
mNotificationBuilder.setLargeIcon(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), bigIcon), 128, 128, true));
}
if (intentClass != null) {
Intent notificationIntent = new Intent(this, intentClass);
PendingIntent pendingIntent = PendingIntent.getActivity(this, REQUEST_CODE, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mNotificationBuilder.setContentIntent(pendingIntent);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
channel.setShowBadge(false);
channel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationManager.createNotificationChannel(channel);
}
return mNotificationBuilder.build();
}
public class LocalBinder extends Binder {
public BaseForegroundServiceJava getService() {
return BaseForegroundServiceJava.this;
}
}
}
private MyService myService;
private boolean mBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
MyService.LocalBinder binder = (MyService.LocalBinder) service;
myService = (MyService) binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
}
};
@Override
public void onStart() {
super.onStart();
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
}
@Override
public void onStop() {
super.onStop();
unbindService(mConnection);
}
public class MyForegroundServiceJava extends BaseForegroundServiceJava {
@Override
protected Notification serviceNotification() {
return createNotification(
"My App",
"My App is running",
R.drawable.ic_notification,
R.drawable.icon,
MainActivity.class
);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingHorizontal="20dp"
android:paddingVertical="15dp">
<TextView
android:id="@+id/txtTitle"
style="@style/TextAppearance.Compat.Notification.Info.Media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is from my service"
android:textColor="#fff" />
<TextView
android:id="@+id/txtResult"
style="@style/TextAppearance.Compat.Notification.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Any text goes here"
android:textColor="#fff" />
</LinearLayout>
</LinearLayout>
@ericgagnon-me
Copy link

Thank you for your code, but I do not understand the file BindService.java. Is it suppose to be a class ? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment