3

I have set an alarm manager at a method setAlarm() at MainActivity that contain a date from firebase database and set an alarm based on that. This is pretty good when I try to run this. But when I try to reboot my phone before the alarm times up, nothing have been happened.

I also have tried to create a Receiver that refer to a service. And from this service onHandleIntent(Intent intent), I call MainActivity.setAlarm(). Also i have been added a permission boot complete at android manifest. After that, I try to restart my phone and when my phone completed booting, the app has force close. I think it stopped cause I call a method at an activity class.

This is My Alarm Receiver

public class AlarmReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
    Intent notificationIntent = new Intent(context, BabyListActivity.class);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(BabyListActivity.class);
    stackBuilder.addNextIntent(notificationIntent);

    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

    Notification notification1 = builder.setContentTitle("1")
            .setContentText("New Notification From Demo App..")
            .setTicker("New Message Alert!")
            .setSmallIcon(R.mipmap.ic_launcher_round)
            .setContentIntent(pendingIntent).build();

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notification1);
}

This is My startAlarm() method

public static void startAlarm(Context context){
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
    notificationIntent.addCategory("android.intent.category.DEFAULT");

    PendingIntent broadcast = PendingIntent.getBroadcast(context, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, 2017);
    cal.set(Calendar.MONTH, 8-1);
    cal.set(Calendar.DAY_OF_MONTH, 10);
    cal.set(Calendar.HOUR_OF_DAY, 10);
    cal.set(Calendar.MINUTE, 15);
    cal.set(Calendar.SECOND, 4);

    alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), broadcast);
}

This is My BootAlarmReceiver

public class BootAlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {

        // It is better to reset alarms using Background IntentService
        Intent i = new Intent(context, BootService.class);
        ComponentName service = context.startService(i);

        if (null == service) {
            // something really wrong here
            Log.e(TAG, "Could not start service ");
        }
        else {
            Log.e(TAG, "Successfully started service ");
        }

    } else {
        Log.e(TAG, "Received unexpected intent " + intent.toString());
    }
}

This is my Boot Service

public class BootService extends Service {


public BootService() {
    super("BootService");
}

@Override
public void onCreate() {
    MainActivity.startAlarm(this);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_NOT_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

This is my android manifest

<receiver android:name=".AlarmReceiver">
        <intent-filter>
            <action android:name="android.media.action.DISPLAY_NOTIFICATION"></action>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

    <service android:name=".BootService"/>

    <receiver android:name=".BootAlarmReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

Can someone tell me how to solve this problem? thanks...

KENdi
  • 7,576
  • 2
  • 16
  • 31
EM Farih
  • 67
  • 1
  • 9

2 Answers2

3

There are at least two mistakes I think. Firstly, you'd never new a Activity class, it should be managed by android framework, if you just want to invoke some methods in it, you'd better extract methods into an utility class or simply change the methods to static which is not recommended. Secondly, onHandleIntent method will run in background thread, you can't invoke methods that should be run at main thread.

So in my opinion, for test, you can just make the startAlarm() method in MainActivity static and BootService extend Service instead of IntentService, do these changes and try again.

change setAlarm() method like this:

public static void startAlarm(Context context){
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
    notificationIntent.addCategory("android.intent.category.DEFAULT");

    PendingIntent broadcast = PendingIntent.getBroadcast(context, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, 2017);
    cal.set(Calendar.MONTH, 8-1);
    cal.set(Calendar.DAY_OF_MONTH, 10);
    cal.set(Calendar.HOUR_OF_DAY, 11);
    cal.set(Calendar.MINUTE, 40);
    cal.set(Calendar.SECOND, 00);

    alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), broadcast);
}

change your BootAlarmReceiver like this:

public class BootService extends Service {


    @Override
    public void onCreate() {
        MainActivity.startAlarm(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Try again!

vesper
  • 264
  • 1
  • 11
  • hi vesper, when i try to make startAlarm() static, there is an error "Error:(121, 52) error: non-static method getSystemService(String) cannot be referenced from a static context".. do you get any idea? thanks before.. – EM Farih Aug 10 '17 at 05:41
  • you can change your `startAlarm()` to `startAlarm(Context context)`,and in `onStartCommand` method in the service, invoke startAlarm(this). – vesper Aug 10 '17 at 06:16
  • You encounter the error is because the code `PendingIntent broadcast = PendingIntent.getBroadcast(this, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);` need a context as parameter, and in your code, 'this' references to your MainActivity, `this` reference cannot use in a static method, so you'd better put the context as a parameter of `setAlarm()` method. – vesper Aug 10 '17 at 06:19
  • when i added a `startAlarm(Context context)` i had this following error : `Error:(116, 9) error: method startAlarm in class MainActivity cannot be applied to given types; required: Context found: no arguments reason: actual and formal argument lists differ in length`... sorry, can you explain more detail... thanks in advance.. – EM Farih Aug 10 '17 at 06:52
  • @EMFarih I have show all codes at my first comment, please try again and let me know the result. – vesper Aug 10 '17 at 07:07
  • sorry before, after adding `context` and `this`, i try restart my phone and still get `has stopped` with this error `FATAL EXCEPTION: IntentService[BootService] java.lang.IllegalStateException: System services not available to Activities before onCreate() at android.app.Activity.getSystemService(Activity.java:5603) at ga.crescere.mom.MainActivity.startAlarm(MainActivity.java:121) at ga.crescere.mom.BootService.onHandleIntent(BootService.java:42)` .. – EM Farih Aug 10 '17 at 07:29
  • Looks like you don't use my codes updated in my first comment, you should use Service instead of IntentService. – vesper Aug 10 '17 at 07:32
  • sorry again, when i change to `Service`, it give me many error like, `Error:(33, 8) error: BootService is not abstract and does not override abstract method onBind(Intent) in Service` and `Error:(36, 9) error: constructor Service in class Service cannot be applied to given types; required: no arguments found: String reason: actual and formal argument lists differ in length` and again `Error:(41, 5) error: method does not override or implement a method from a supertype`.. so i didnt change it.. do you have any idea.. – EM Farih Aug 10 '17 at 07:47
  • Can you update all your changed codes? I don't sure what your codes looks like now. – vesper Aug 10 '17 at 07:54
  • I'm so sorry, i didn't realize your first comment.. sorry .. now i change my code like yours, now giving me an error `Error:(121, 52) error: non-static method getSystemService(String) cannot be referenced from a static context` and `Error:(16, 9) error: constructor Service in class Service cannot be applied to given types; required: no arguments found: String reason: actual and formal argument lists differ in length`.. Sorry.. and thank you very much for your reply.. – EM Farih Aug 10 '17 at 08:07
  • just change `AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);` to `AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);` – vesper Aug 10 '17 at 09:10
  • now only the second one error `Error:(16, 9) error: constructor Service in class Service cannot be applied to given types; required: no arguments found: String reason: actual and formal argument lists differ in length`.. do you have a solution? – EM Farih Aug 10 '17 at 09:27
  • Can you print all stack info? – vesper Aug 10 '17 at 09:36
  • stack info? it not compiled yet caused by error above.. above error happened at this line `super("BootService");`.. – EM Farih Aug 10 '17 at 13:29
  • I know now, just remove the constructor of BootService, you'd better read here: https://developer.android.com/reference/android/app/Service.html to learn the usage of Service. In the meaning time, I have updated my first comment. – vesper Aug 11 '17 at 00:56
  • NOW, You're on it... Thank you very much for your help @vesper – EM Farih Aug 11 '17 at 06:41
2

Try this..

public class RebootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

        Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
        notificationIntent.addCategory("android.intent.category.DEFAULT");

        PendingIntent broadcast = PendingIntent.getBroadcast(context, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2017);
        cal.set(Calendar.MONTH, 8-1);
        cal.set(Calendar.DAY_OF_MONTH, 10);
        cal.set(Calendar.HOUR_OF_DAY, 10);
        cal.set(Calendar.MINUTE, 15);
        cal.set(Calendar.SECOND, 4);

        alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), broadcast);
        }
    }
}

Then in your manifest..

<receiver android:name=".RebootReceiver">
<intent-filter>
  <action android:name="android.intent.action.BOOT_COMPLETED" /> 
  <action android:name="android.intent.action.QUICKBOOT_POWERON" /> 
  <category android:name="android.intent.category.DEFAULT" /> 
  </intent-filter>
  </receiver>
Sakura Fukuyoshi
  • 1,461
  • 1
  • 10
  • 14