App crashes when creating an Alarmobject - Alarmmanager - java

I searched a lot but I couldn't find an answer for my specific problem, so I'm asking my own question.
The Problem:
I'm programming an app where a user can set multiple alarms with different repeating intervals. But when I create an Alarm object the app crashes.
Every time the user clicks a button the Alarm class is called with:
Alarm b = new Alarm(name, intervall, 23, 30, 15, 6, 2016);
This is my Alarm class:
package witty.de.witty;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.IBinder;
import java.util.Calendar;
public class Alarm extends Activity {
public Alarm(String name, int intervall, int stunden, int minuten, int tag, int monat, int jahr) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, jahr);
cal.set(Calendar.MONTH, (monat - 1));
cal.set(Calendar.DAY_OF_MONTH, tag);
cal.set(Calendar.HOUR_OF_DAY, stunden);
cal.set(Calendar.MINUTE, minuten);
cal.set(Calendar.SECOND, 0);
Intent myIntent = new Intent(Alarm.this, AlarmReceiver.class);
final int _id = (int) System.currentTimeMillis();
myIntent.setData(Uri.parse("reminder:" + _id));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, _id, myIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), intervall * AlarmManager.INTERVAL_DAY,
pendingIntent);
}
}
And this is my NotificationService class:
package witty.de.witty;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
import java.util.logging.Logger;
import witty.de.witty.MainActivity;
import witty.de.witty.R;
public class NotificationService extends Service {
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast mToast = Toast.makeText(
this,
"Reminders added to the calendar successfully for ",
Toast.LENGTH_LONG);
mToast.show();
// Getting Notification Service
mManager = (NotificationManager) this.getApplicationContext()
.getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),
MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(
this.getApplicationContext(), 0, intent1,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Witty2")
.setContentIntent(pendingNotificationIntent)
.setContentText("Errinerung!!");
mManager.notify(0, mBuilder.build());
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
This is my AlarmReceiver class:
package witty.de.witty;
import android.app.NotificationManager;
import android.content.Context;
import android.support.v4.app.NotificationCompat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, NotificationService.class);
context.startService(myIntent);
}
}
And this is my AndroidManifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="witty.de.witty">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Erstellen"></activity>
<activity android:name=".Impressum"></activity>
<activity android:name=".Startseite"></activity>
<service android:name=".NotificationService"></service>
<receiver android:name=".AlarmReceiver" android:process=":remote"></receiver>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
If you need more code or more information, just ask me.

My solution:
Call the Alarm class with a new intent not as an Object:
Intent intent = new Intent(this, Alarm.class);
startActivity(intent);

Related

How to send a notification at the exact time when the application is closed?

I am new to android studio. I need to create a note application with a reminder function. I decided to do this through the alarmmanager, but it only works when the application is open. Is it realistic to do this only through services?
I noticed that in the google keep application, when creating a reminder, a new service is created. How to do this?
Part of the code from the activity:
public void alarm(Calendar c) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertReceiver.class);
intent.putExtra("title",editTask.getText().toString());
PendingIntent pen = PendingIntent.getBroadcast(this, 1, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),pen);
AlertReciver.java
package denchic45.myapp.appmy;
import android.content.BroadcastReceiver;
import android.content.Intent; import android.widget.Toast;
import android.content.Context;
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent = new Intent(context, Services.class);
context.startService(intent);
Toast.makeText(context, "alarm", Toast.LENGTH_SHORT).show();
} }
Services.java
package denchic45.myapp.appmy;
import android.app.IntentService;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class Services extends IntentService {
public Services() {
super("public services");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Context context = getApplicationContext();
Toast.makeText(context, "WORK", Toast.LENGTH_SHORT).show();
final String CHANNEL_ID = "1";
if(Build.VERSION.SDK_INT = Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,"001",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("description");
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("dd")
.setSmallIcon(R.mipmap.ic_launcher);
notification.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(1,notification.build());
} else {
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("dd")
.setSmallIcon(R.drawable.note)
.setChannelId(CHANNEL_ID);
notification.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(1,notification.build());
}
} }
Part of the code from the manifest:
<receiver android:name=".AlertReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".Services"/>

How to start activity or service (Either) on bootup completed?

I'm trying to find out how to run a service (Any service, may be foreground or background) when device boots. I've tried implementing broadcast receiver but it seems not to work.
Below is my full code.
1.AndroidManifext.xml - I made sure I included the service and broadcast receiver here. Are there any permissions I may be lacking?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.testboot">
<!-- Example need below permission. -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name="com.example.testboot.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.example.testboot.BootDeviceReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service
android:name="com.example.testboot.RunAfterBootService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
2.MainActivity.java - This is the launch class, I made it call the broadcast receiver class. Asides from that, it doesn't have anything else.
package com.example.testboot;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent("com.example.testboot.BootDeviceReceiver");
sendBroadcast(intent);
}
}
3.BootDeviceReceiver.java -This is the class responsible for knowing when device has booted up (Extends Broadcast receiver)
package com.example.testboot;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class BootDeviceReceiver extends BroadcastReceiver {
private static final String TAG_BOOT_BROADCAST_RECEIVER = "BOOT_BROADCAST_RECEIVER";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String message = "BootDeviceReceiver onReceive, action is " + action;
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
Log.d(TAG_BOOT_BROADCAST_RECEIVER, action);
if(Intent.ACTION_BOOT_COMPLETED.equals(action))
{
//startServiceDirectly(context);
startServiceByAlarm(context);
}
}
/* Start RunAfterBootService service directly and invoke the service every 10 seconds. */
private void startServiceDirectly(Context context)
{
try {
while (true) {
String message = "BootDeviceReceiver onReceive start service directly.";
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
Log.d(TAG_BOOT_BROADCAST_RECEIVER, message);
// This intent is used to start background service. The same service will be invoked for each invoke in the loop.
Intent startServiceIntent = new Intent(context, RunAfterBootService.class);
context.startService(startServiceIntent);
// Current thread will sleep one second.
Thread.sleep(10000);
}
}catch(InterruptedException ex)
{
Log.e(TAG_BOOT_BROADCAST_RECEIVER, ex.getMessage(), ex);
}
}
/* Create an repeat Alarm that will invoke the background service for each execution time.
* The interval time can be specified by your self. */
private void startServiceByAlarm(Context context)
{
// Get alarm manager.
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// Create intent to invoke the background service.
Intent intent = new Intent(context, RunAfterBootService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long startTime = System.currentTimeMillis();
long intervalTime = 60*1000;
String message = "Start service use repeat alarm. ";
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
Log.d(TAG_BOOT_BROADCAST_RECEIVER, message);
// Create repeat alarm.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, startTime, intervalTime, pendingIntent);
}
}
3.RunAfterBootService.java - This is the service class, should be displayed after device completes booting up.
package com.example.testboot;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;
public class RunAfterBootService extends Service {
private static final String TAG_BOOT_EXECUTE_SERVICE = "BOOT_BROADCAST_SERVICE";
public RunAfterBootService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG_BOOT_EXECUTE_SERVICE, "RunAfterBootService onCreate() method.");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String message = "RunAfterBootService onStartCommand() method.";
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
Log.d(TAG_BOOT_EXECUTE_SERVICE, "RunAfterBootService onStartCommand() method.");
Intent i = new Intent();
i.setClass(RunAfterBootService.this,MainActivity.class);
startActivity(i);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
So far, when I restart my device nothing happens at all.
Has your app an icon ? you must open your app one time then you can receive the boot_complete broadcast.

How to receive ACTION_SCREEN_OFF with a "always running" service

I want to create an app that set/reset a timer to reproduce a song if the mobile spend 8 hours with the screen off.
I want to create a service that receive ACTION_SCREEN_OFF, but the problem is that when the app is killed from recent apps, the service is killed. I try with START_STICKY but the service is not restarted (onCreate is called sometimes but not onStart Command). I try to set in Manifest but the receiver must be register.
By now I only want that receiver detect ACTION_SCREEN_OFF.
I Have this code:
MainScreen.java (MainActivity)
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainScreen extends Activity implements View.OnClickListener{
public static final String MSG_TAG = "NoSleepMore";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
findViewById(R.id.start_service_button).setOnClickListener(this);
findViewById(R.id.stop_service_button).setOnClickListener(this);
}
#Override
public void onClick(View v){
Intent intent = new Intent(getApplicationContext(), LockService.class);
switch (v.getId()) {
case R.id.start_service_button:
Log.e(MSG_TAG,"Service started");
//starts service for the given Intent
startService(intent);
break;
case R.id.stop_service_button:
Log.e(MSG_TAG,"Service stopped");
//stops service for the given Intent
stopService(intent);
break;
}
}
}
LockService.java
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
public class LockService extends Service {
#Override
public IBinder onBind(Intent arg0) {
Log.i(MainScreen.MSG_TAG, "onBind()" );
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(MainScreen.MSG_TAG, "Service Created");
/* Filtrar Acciones Capturadas */
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
// Listener
final BroadcastReceiver mReceiver = new ScreenReceiver();
// Registar Listener
registerReceiver(mReceiver, filter);
return Service.START_STICKY;
//return super.onStartCommand(intent, flags, startId);
}
#Override
public void onCreate() {
Log.i(MainScreen.MSG_TAG, "onCreate()");
}
#Override
public void onDestroy() {
Log.i(MainScreen.MSG_TAG, "onDestroy()");
}
}
ScreenRecive.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ScreenReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.i(MainScreen.MSG_TAG,"OnReceive->");
// Log Handel
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// do whatever you need to do here
Log.i(MainScreen.MSG_TAG,"Screen action OFF");
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// and do whatever you need to do here
Log.i(MainScreen.MSG_TAG,"Screen action ON");
}else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
Log.e(MainScreen.MSG_TAG,"Action UserPresent");
}
}
}
AndroidManifext.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="es.mangel.nosleepmore">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ScreenReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SCREEN_ON"/>
<action android:name="android.intent.action.ACTION_SCREEN_OFF"/>
<action android:name="android.intent.action.ACTION_USER_PRESENT"/>
</intent-filter>
</receiver>
<service android:name=".LockService" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</service>
</application>
</manifest>
The Main activity is just two buttons.
BTW I just need that run over Android 8.0.

AlarmManager does not work in foreground service, when app was killed

My application should send notifications at the specified time.
I wrote a service that uses AlarmManager, a receiver that restarts it if you close the application. The service is restarted (as can be seen in the logs), but AlarmManager does not work (the receiver does not receive an intent from it) while the application is closed. I also tried to register the receiver in the service code - it still does not work (
AlarmService - foreground service. AlarmSetter - class to set Alarms.
AlarmReceiver - receiver to send notifications (has log: intent received)
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="net.ozero.drugsreminder"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUICKBOOT_POWERON" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
>
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.AddPrescActivity"
android:label="#string/label_add_presc_activity"
android:parentActivityName=".activities.MainActivity"
android:theme="#style/ActionBarTheme"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activities.AddDrugActivity"
android:label="#string/label_add_drug_activity"
android:parentActivityName=".activities.AddPrescActivity"
android:theme="#style/ActionBarTheme"
android:windowSoftInputMode="stateVisible">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.AlarmActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name=".services.AlarmService"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="net.ozero.drugsreminder.services.AlarmService.MarkEvent" />
<action android:name="net.ozero.drugsreminder.services.AlarmService.SetLater" />
</intent-filter>
</service>
<receiver
android:name=".services.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="net.ozero.drugsreminder.services.AlarmReceiver" />
</intent-filter>
</receiver>
<receiver
android:name=".services.RestartAlarmServiceReceiver"
android:enabled="true"
android:exported="true">
</receiver>
<receiver
android:name=".services.BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
</application>
</manifest>
AlarmService:
package net.ozero.drugsreminder.services;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import net.ozero.drugsreminder.alarm.AlarmSetter;
import net.ozero.drugsreminder.database.DBHelper;
import net.ozero.drugsreminder.datastructure.Event;
import net.ozero.drugsreminder.formatters.AlarmMessageBuilder;
import java.util.List;
import static net.ozero.drugsreminder.App.*;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
/**TODO alarm repeating (bug) */
public class AlarmService extends Service {
public AlarmService() {
}
public DBHelper mDBHelper;
public AlarmReceiver mAlarmReceiver;
public AlarmManager mAlarmManager;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("AlarmService:", "on start");
// mAlarmReceiver = new AlarmReceiver();
mDBHelper = new DBHelper(this);
//set event is done
if (isMarkAction(intent)) {
markEvent(intent);
}
//set event to alarm later
if (isSetLaterAction(intent)) {
setEventLater(intent);
}
setAlarms();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.i("AlarmService:", "on removed");
sendBroadcast(new Intent(this, RestartAlarmServiceReceiver.class));
Log.i(getClass().getName(), "OnTaskRemoves: broadcast sent");
super.onTaskRemoved(rootIntent);
}
private boolean isMarkAction(Intent intent) {
return (
intent != null
&& intent.getAction() != null
&& intent.getAction().equals(ACTION_MARK_EVENT)
);
}
private boolean isSetLaterAction(Intent intent) {
return (
intent != null
&& intent.getAction() != null
&& intent.getAction().equals(ACTION_SET_LATER)
);
}
private void setEventLater(Intent intent) {
int id = intent.getIntExtra(EXTRA_ALARM_ID, 0);
mDBHelper.setEventLater(id, ALARM_INTERVAL);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.cancel(id);
Log.i("AlarmService:", "event time set later : " + id);
}
private void markEvent(Intent intent) {
int id = intent.getIntExtra(EXTRA_ALARM_ID, 0);
mDBHelper.markEvent(id);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.cancel(id);
Log.i("AlarmService:", "event is marked, id : " + id);
}
private void setAlarms() {
mDBHelper = new DBHelper(this);
List<Event> events = mDBHelper.getActualEvents();
Log.i("AlarmService:setAlarms:", "actual (not marked) events size:" + String.valueOf(events.size()));
AlarmSetter alarmSetter = new AlarmSetter(this);
AlarmMessageBuilder alarmMessageBuilder = new AlarmMessageBuilder(mDBHelper);
for (Event event : events) {
long timeMillis = event.getReceptionDateTime().getTime();
String message = alarmMessageBuilder.getMessage(event);
int id = event.getId();
alarmSetter.setAlarm(timeMillis, message, id);
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(getClass().getName(), "onDestroy");
}
}
AlarmSetter:
package net.ozero.drugsreminder.alarm;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import net.ozero.drugsreminder.services.AlarmReceiver;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_MESSAGE;
public class AlarmSetter {
//one minute timeout
public static final long DEFAULT_ALARM_TIMEOUT = 60*1000L;
private Context mContext;
private AlarmManager mAlarmManager;
public AlarmSetter(Context applicationContext) {
mContext = applicationContext;
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Log.i("AlarmSetter:", "alarm manager:" + mAlarmManager);
}
//main method
public void setAlarm(long timeMillis, String message, int id) {
//creating intent for alarm message
Intent intent = new Intent("net.ozero.drugsreminder.services.AlarmReceiver");
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.putExtra(EXTRA_ALARM_MESSAGE, message);
intent.putExtra(EXTRA_ALARM_ID, id);
//creating pending intent
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext.getApplicationContext(), id, intent, 0);
//setting alarm
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
timeMillis,
pendingIntent
);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
timeMillis,
pendingIntent
);
} else {
mAlarmManager.set(
AlarmManager.RTC_WAKEUP,
timeMillis,
pendingIntent
);
}
Log.i("AlarmSetter:" , "alarm set");
}
}
AlarmReceiver:
package net.ozero.drugsreminder.services;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import net.ozero.drugsreminder.alarm.NotificationSetter;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_MESSAGE;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("AlarmReceiver:", "notification received");
String message = intent.getStringExtra(EXTRA_ALARM_MESSAGE);
int id = intent.getIntExtra(EXTRA_ALARM_ID, 1);
NotificationSetter notificationSetter = new NotificationSetter(context);
notificationSetter.setNotification(message, id);
}
}
You have to run your service as a real foreground service so that it will survive even if your app has been closed or finished.
This is a very simple sample from http://www.vogella.com/tutorials/AndroidServices/article.html:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

Android – Background Service does not run if Phone is Asleep

I am trying to make an application for my school that includes a background service that will download a student's grades, and assignment history. The service is called every hour by an AlarmManager, and it works, but only as long as the device is powered on. As soon as the device is turned on (from a state of hibernation; the device is not completely shut down), the AlarmManager triggers the service. This is the code of the BroadcastReceiver, which includes the AlarmManager:
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.support.v4.content.WakefulBroadcastReceiver;
public class ServiceAlarmReceiver extends WakefulBroadcastReceiver {
private final String TAG = "com.example.ahsandroidapplication";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Broadcast received");
Intent gradeNotificationServiceIntent = new Intent(context, GradeNotificationService.class);
//context.startService(gradeNotificationServiceIntent);
startWakefulService(context, gradeNotificationServiceIntent);
}
public static void setAlarm(Context context){
System.out.println("Service started");
long alertTime = System.currentTimeMillis() + 1000 * 60 * 60;
Intent alertIntent = new Intent(context, ServiceAlarmReceiver.class);
alertIntent.setAction("com.example.ahsandroidapplication.servicealarmbroadcast");
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
//alarmManager.set(AlarmManager.RTC_WAKEUP, alertTime, PendingIntent.getBroadcast(context, 1, alertIntent,
// PendingIntent.FLAG_UPDATE_CURRENT));
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alertTime, 1000 * 3600, PendingIntent.getBroadcast(context,
GradeNotificationService.SERVICE_ALARM_BROADCAST_ID, alertIntent,
PendingIntent.FLAG_UPDATE_CURRENT));
}
public static void cancelAlarm(Context context)
{
Intent intent = new Intent(context, ServiceAlarmReceiver.class);
intent.setAction("com.example.ahsandroidapplication.servicealarmbroadcast");
PendingIntent sender = PendingIntent.getBroadcast(context,
GradeNotificationService.SERVICE_ALARM_BROADCAST_ID, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
Because the broadcast is received only when the phone is turned on, I believe the problem lies in the receiver.
There is another problem with the service. It is supposed to send a push notification whenever a new grade is posted, but they are never being sent.
Here is the code for the service class:
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v4.app.NotificationCompat;
public class GradeNotificationService extends IntentService {
private Context context;
public GradeNotificationService() {
super("GradeNotificationService");
// TODO Auto-generated constructor stub
}
public static final int SERVICE_ALARM_BROADCAST_ID = 0;
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
System.out.println("Grade notification services started");
context = getApplicationContext();
final Intent completeWakefulIntent = intent;
if(gradesChanged()){
getAssignments();
}
ServiceAlarmReceiver.completeWakefulIntent(completeWakefulIntent);
}
private boolean gradesChanged() {
//Massive blocks of code that will take you forever to read
}
private void getAssignments(){
//Massive blocks of code that will take you forever to read
//It is in this method that sendNotification() is used to send a notification
//(at least that's what it's supposed to be doing)
}
private void sendNotification(String title, String message){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
mBuilder.setContentTitle(title);
mBuilder.setContentText(message);
mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
Intent resultIntent = new Intent(context, MainInterface.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, 0);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
}
private boolean networkIsAvailable() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
// return netInfo != null && netInfo.isConnectedOrConnecting();
NetworkInfo mWifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return netInfo != null && netInfo.isConnectedOrConnecting()
|| mWifi.isConnected();
}
}
Can anyone tell me what I can do to make this service run when the phone is asleep, or why it is not sending any notifications? Any help is appriciated.
Edit:
This is most of the manifest. The target sdk is 21 and the minimum is 11:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/ic_launcher">
<service
android:name="com.example.ahsandroidapplication.GradeNotificationService"
android:enabled="true" >
<intent-filter>
<action android:name="com.example.ahsandroidapplication.ServiceAlarmReceiver" />
</intent-filter>
</service>
<receiver android:name=".ServiceAlarmReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.example.ahsandroidapplication.servicealarmbroadcast"></action>
</intent-filter>
</receiver>
<receiver android:name=".BootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
<activity
android:name="MainInterface"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="MainLogin"
android:label="#string/app_name">
</activity>
<service android:enabled="true"
android:exported="false"
android:isolatedProcess="false"
android:label="#string/app_name"
android:name="AspenManager" >
</service>
</application>
"Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested."
http://developer.android.com/reference/android/app/AlarmManager.html

Categories