When I try to start a service, i get a null pointer exception which is caused by instantiating a notificationmanager. This seems fairly simple, just instantiating, but this one line of code causes the application to crash.
What is the cause of this problem?
starting service in onStop method:
@Override
protected void onStop() {
super.onStop();
Intent notifService = new Intent(getApplicationContext(), NotificationService.class);
startService(notifService);
}
service class:
package ch.zli.eb.myfitnessjourney.service;
public class NotificationService extends Service {
private String channelId = "myfitnessjourney_1";
private int notificationId = 101;
NotificationManager notifManager = getSystemService(NotificationManager.class);
private LocalBinder myBinder = new LocalBinder();
private Timer notifTimer;
private TimerTask notifTimerTask;
private final int intervalSec = 5;
private Handler notifHandler;
public NotificationService() throws ParseException {
createNotificationChannel();
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
try {
startTimer();
} catch (ParseException e) {
e.printStackTrace();
}
return START_STICKY;
}
@Override
public void onCreate() {
}
@Override
public void onDestroy() {
stopTimerTask();
super.onDestroy();
}
public void startTimer() throws ParseException {
notifTimer = new Timer();
initializeTimerTask();
notifTimer.schedule(notifTimerTask, 5000, intervalSec * 1000);
}
public void stopTimerTask() {
if (notifTimer != null) {
notifTimer.cancel();
notifTimer = null;
}
}
public void initializeTimerTask() throws ParseException {
DbManager dbManager = new DbManager(this);
ArrayList<Goal> goalList = dbManager.getGoals();
// REQUIRED DATE FORMAT
DateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
dateFormatter.setLenient(false);
Date todaysDate = dateFormatter.parse(dateFormatter.format(new Date()));
notifTimerTask = new TimerTask() {
public void run() {
notifHandler = new Handler();
notifHandler.post(new Runnable() {
public void run() {
for (Goal g : goalList) {
if (g.isReminders()) {
if (g.getEndDate().compareTo(todaysDate) == 0) {
sendNotification(g);
}
}
}
}
});
}
};
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String notifTitle = "Title";
String notifDesc = "Description";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel notifChannel = new NotificationChannel(channelId, notifTitle, importance);
notifManager.createNotificationChannel(notifChannel);
}
}
private void sendNotification(Goal g) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setContentTitle("Goal Deadline")
.setContentText(g.getName() + "is about to pass the deadline!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
notifManager.notify(notificationId, builder.build());
}
public class LocalBinder extends Binder {
NotificationService getService() {
return NotificationService.this;
}
}
}
getSystemService(Class serviceClass) is a method of abstract class Context. So if you are calling this method from a non-activity class, you will need to pass the context of the activity class to your service class. You can pass this in a constructor.
Context mContext;
public NotificationService(Context mContext) {
this.mContext = mContext;
}
NotificationManager notifManager = mContext.getSystemService(NotificationManager.class);