3

I created an app to send message using alarm manager but if i put an alarm for a long duration the app is killed by android automatically, so i need to prevent the app from getting killed.Please tell me how can I do it.

Calendar cal = Calendar.getInstance();
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
if (currentApiVersion > android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
    cal.set(Calendar.MINUTE, time_picker.getMinute());
    cal.set(Calendar.HOUR_OF_DAY, time_picker.getHour());
} else {
    //Setting the date and time from the time picker
    cal.set(Calendar.MINUTE, time_picker.getCurrentMinute());
    cal.set(Calendar.HOUR_OF_DAY, time_picker.getCurrentHour());
}
//System clock time
Calendar c = Calendar.getInstance();
Long a ;//=(long) (Calendar.getInstance().get(Calendar.SECOND) * 1000);
if(cal.get(Calendar.HOUR_OF_DAY) < c.get(Calendar.HOUR_OF_DAY))
    h = (cal.get(Calendar.HOUR_OF_DAY) + 24 - c.get(Calendar.HOUR_OF_DAY)) * 60;
else
    h = (cal.get(Calendar.HOUR_OF_DAY) - c.get(Calendar.HOUR_OF_DAY * 60;
m = (cal.get(Calendar.MINUTE) - c.get(Calendar.MINUTE));
a = (m + h) * 60;
myIntent = new Intent(this, MyReceiver.class);
myIntent.putExtra("pos", array.select);


//Pending Intent for sending the intent afterwards
pendingIntent[array.select] = PendingIntent.getBroadcast(this.getApplicationContext(), array.select, myIntent, 0);
alarmManager[array.select] = (AlarmManager) (this.getSystemService(Context.ALARM_SERVICE));
alarmManager[array.select].set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + a * 1000, pendingIntent[array.select]);

pendingarray.add(pendingIntent[array.select]);
sms_list.Phone[array.select] = Phone;
Intent back = new Intent(this, sms_list.class);
back.putExtra("PHONE", Phone);
back.putExtra("Flag",2);
back.putExtra("MSG", Message);
back.putExtra("HOUR", (int) cal.get(Calendar.HOUR_OF_DAY));
back.putExtra("MIN", (int) cal.get(Calendar.MINUTE));
back.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(back);

If the answer is wake lock can you please tell me where to use it.

Johann67
  • 385
  • 6
  • 16
Pritesh
  • 139
  • 2
  • 12

3 Answers3

3

You can use a service to do it, this will also work after the device is rebooted. You also have to make the service foreground to prevent the system from killing it. It can be done by adding an ongoing notification. See the service code below.

In your Manifest add the following

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

    <service
        android:name=".StarterService"
        android:enabled="true"
        android:exported="true" />

Then create a new class as follows:

public class Autostart extends BroadcastReceiver {

    /**
     * Listens for Android's BOOT_COMPLETED broadcast and then executes
     * the onReceive() method.
     */
    @Override
    public void onReceive(Context context, Intent arg1) {
        Log.d("Autostart", "BOOT_COMPLETED broadcast received. Executing starter service.");

        Intent intent = new Intent(context, StarterService.class);
        context.startService(intent);
    }
}

And finally your service as follows:

public class StarterService extends Service {
    private static final String TAG = "MyService";

    /**
     * starts the AlarmManager.
     */

    @Override
    public void onCreate() {
        super.onCreate();
        //TODO: Start ongoing notification here to make service foreground
    }
    @Override
    public void onStart(Intent intent, int startid) {

       //TODO: Put your AlarmManager code here
       //TODO: you also need to add some logic to check if some previous work is pending in case of a device reboot
        Log.d(TAG, "onStart");
    }

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

    @Override
    public void onDestroy() {
        //TODO: cancel the notification
        Log.d(TAG, "onDestroy");
    }
}

Now all you need to do is call the service whenever you need to send the message. PS: I know an answer is accepted but hope this helps you or someone else.

Community
  • 1
  • 1
Shantanu
  • 1,190
  • 1
  • 13
  • 23
1

An alarm should be triggered in a Broadcast Receiver.

If it performs long-lived operations, you should then use threads or Services. Both of them can be launched from a receiver.

EDIT

As a short example, I use this method in a button's onClickListener in the activity :

scheduleAlarm(name);

Method :

public void scheduleAlarm(String client)
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
    String delay = sharedPref.getString(SettingsActivity.PREF_DELIVERY_DELAY, "48");

// time at which alarm will be scheduled here alarm is scheduled at 1 day from current time,
// we fetch  the current time in milliseconds and added 1 day time
// i.e. 24*60*60*1000= 86,400,000   milliseconds in a day
Long time = new GregorianCalendar().getTimeInMillis()+ Integer.parseInt(delay) * 1000; //todo change seconds to hours

// create an Intent and set the class which will execute when Alarm triggers, here we have
// given AlarmReciever in the Intent, the onRecieve() method of this class will execute when
// alarm triggers and
//we will write the code to send SMS inside onRecieve() method pf Alarmreciever class
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
intentAlarm.putExtra("CLIENT", client);

// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

//set the alarm for particular time
//todo string res
alarmManager.set(AlarmManager.RTC_WAKEUP,time, PendingIntent.getBroadcast(this,1,  intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
Toast.makeText(this, "Alarm Scheduled in " + delay + " hours", Toast.LENGTH_LONG).show();

}

And finally, the AlarmReceiver.java

package com.patrickmiller.test2;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent)
    {
        Toast.makeText(context, "Alarm received", Toast.LENGTH_SHORT).show();

        String client = intent.getStringExtra("CLIENT");

        Notify(context, client);
    }

    public void Notify(Context context, String client) {

        //todo expanded layout with options Fiche de contact | Rapport and cover image
        //todo send name, address, phone, email and id through Intent to ContactClientActivity
        //todo delete notification when generated


        try {
            NotificationCompat.Builder mBuilder =
                    new NotificationCompat.Builder(context)
                            //todo set notification icon, content title and content text as string resources
                            .setSmallIcon(R.drawable.warning)
                            .setContentTitle(client)
                            .setContentText("N'oubliez pas de générer le rapport du client");

            Intent resultIntent = new Intent(context, ContactClientActivity.class);

            //todo may need to expend instead of calling activity. Buttons will do.
            // Because clicking the notification opens a new ("special") activity, there's
            // no need to create an artificial back stack.
            PendingIntent resultPendingIntent =
                    PendingIntent.getActivity(
                            context,
                            0,
                            resultIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT
                    );

            mBuilder.setContentIntent(resultPendingIntent);

            // Sets an ID for the notification
            int mNotificationId = 001;

            // Gets an instance of the NotificationManager service
            NotificationManager mNotifyMgr = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);

            // Builds the notification and issues it.
            mNotifyMgr.notify(mNotificationId, mBuilder.build());

        }

        catch(Exception e) {
            Toast.makeText(context, String.valueOf(e), Toast.LENGTH_LONG).show();
        }

    }

}

You don't have to care about the client's thing. Just the way I scheduled the alarm..

My operation is a short-lived one, which is sending a notification. If you plan a long-lived operation, you should start a service or a thread from the receiver (onReceive callback method).

Alexandre Martin
  • 1,472
  • 5
  • 14
  • 27
0

ok, your app is finished because is running in the main thread, so you need to make this process in other thread that is not killed when the app is closed. check this documentation from the official page. if you decide start using asyncTask class check this reference

Community
  • 1
  • 1
Rene Limon
  • 614
  • 4
  • 16
  • 34
  • yes, because when you close the app the task continue working in background while some condition is acomplished, the only problem with this class is that stops when devices rotate. So my tip is, you need to read the docs and decide which one is the most suitable for your app – Rene Limon Jun 14 '16 at 15:00
  • Bro as i am using multiple alarm manager classes so will this method work for me. – Pritesh Jun 14 '16 at 16:28
  • Check this https://android-arsenal.com/tag/9 It have a lot of libraries for tasks in backgroud, in special I would use this one: https://android-arsenal.com/details/1/1878 – Rene Limon Jun 14 '16 at 16:37