I want to do some network job periodically even when app if force closed.
Now it works until it's force closed.
What i am missing?
Also if i add to manifest this: android:process=":remote" - it's not triggering onReceive method (like app is force closed), but in logs i found that:
V/AlarmManager: triggered: cmp=com.cryptorulezz.cryptosignals/.Code.Alarm Pkg: com.cryptorulezz.cryptosignals
My code:
public class Alarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
// Put here YOUR code.
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example
System.out.println("ALARM !!!!!!!!!!!!!!!!!!!!");
wl.release();
}
public void setAlarm(Context context)
{
AlarmManager am =(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
//Intent i = new Intent(context, Alarm.class);
Intent i = new Intent("Coinsider.START_ALARM");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 1, pi); // Millisec * Second * Minute
}
public void cancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
How i set alarm in MainActivity:
Alarm alarm = new Alarm();
alarm.setAlarm(this);
Manifest:
<receiver android:name=".Code.Alarm" android:exported="false">
<intent-filter>
<action android:name="Coinsider.START_ALARM" >
</action>
</intent-filter>
</receiver>
Once the app gets force killed, it won't receive the intent and the intent filter won't be triggered. To overcome this, I suggest a sort of watchDog, that relies on some system events (like android.intent.action.BOOT_COMPLETED), that simply checks if one of your process is alive, and fires it if not. In the manifest, you 'd have something like this:
<receiver
android:name="it.angelic.receivers.WatchDogSetupReceiver"
android:process=":souliss_process">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_PRESENT"/>
</intent-filter>
</receiver>
The class WatchDogSetupReceiver would then check if the dog is alive, and fire a new one if needed:
Intent i = new Intent(ctx, WatchDogEventReceiver.class); // explicit intent
PendingIntent patTheDog = PendingIntent.getBroadcast(ctx, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), 5000,
patTheDog);
Last, WatchDogEventReceiver would simply do the required un-killable job. It is important that the watchdog stays light, as it will be fired upon every screen on event. This solution is non-optimal, but works even after force-kill:
public class WatchDogEventReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context ctx, final Intent intent) {
Log.d(Constants.TAG + ":WatchDog", "WatchDog.onReceive() called, looking for Dataservice:");
ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
//Fire Service
Intent eventService = new Intent(ctx, YourDamnService.class);
ctx.startService(eventService);//sempre, ci pensa poi lui
}
Related
I set alarm manager for time control.My purpose continue to time controlling on screen off. While screen is on everything is ok but when i locked to device(screen of) my broadcast receiver not receiver anything
i tried lots of different solution (in Manifest export:false or process:":remote") about similar problem but problem not solved. I need to help. I hope someone solved that problem before.
For set alarm manager
AlarmManager alarmManager = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, TimeService.class);
intent.setAction(SETUP_TIMER_FOR_NOTIFICATION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 112, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long now = System.currentTimeMillis();
long minute = 1000 * 60;
alarmManager.cancel(pendingIntent);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() , minute, pendingIntent);
My Receiver
public class TimeService extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TimeService", "onReceive");
Intent timeIntent = new Intent(context, NotificationService.class);
timeIntent.setAction(SETUP_TIMER_FOR_NOTIFICATION);
startWakefulService(context, timeIntent);
}
}
Manifest.xml
<receiver
android:name="service.TimeService"
android:enabled="true"
android:exported="false"
>
<intent-filter>
<action android:name="alarm_timer_for_notification" />
</intent-filter>
</receiver>
setAndAllowWhileIdle this is worked when screen is off and phone in idle mode
In marshmallow introduce the doze mode for battery saving. So the alarm not fired correctly in repeat mode.
So we use
https://developer.android.com/reference/android/app/AlarmManager.html#setAndAllowWhileIdle(int,%20long,%20android.app.PendingIntent)
From marshmallow and up, alarm waked up only 10 min interval,setAndAllowWhileIdle also fire service or notification 10 minutes once when phone is idle (screen is off).
In normal mode time interval working fine (I have checked 3 min's interval)
public class TimeService extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TimeService", "onReceive");
Intent timeIntent = new Intent(context, NotificationService.class);
timeIntent.setAction(SETUP_TIMER_FOR_NOTIFICATION);
startWakefulService(context, timeIntent);
setAlarm(context);
}
public void setAlarm(Context context)
{
Timber.v(TAG +"set Alarm");
PreferencesHelper preferencesHelper =new PreferencesHelper(context);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, TimeService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
int intervalInMinutes = preferencesHelper.getInt(context.getResources().getString(R.string.sha_loc_intervals), 1)* 60000;
if (android.os.Build.VERSION.SDK_INT >= 23) {
alarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+intervalInMinutes , pendingIntent);
} else if (android.os.Build.VERSION.SDK_INT >= 19
&& android.os.Build.VERSION.SDK_INT < 23) {
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+intervalInMinutes , pendingIntent);
} else {
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+intervalInMinutes , pendingIntent);
}
}
public void cancelAlarm(Context context)
{
Timber.v(TAG +"cancel Alarm");
Intent intent = new Intent(context, TimeService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}}
<receiver android:name=".TimeService"
android:enabled="true"
android:exported="true"
android:process=":remote">
</receiver>
In MainActivity.class
TimeService timeService =new TimeService();
timeService.setAlarm(MainActivity.this);
You want to take a permission in manifest file.
uses-permission android:name="android.permission.WAKE_LOCK"
WakeLock is a mechanism to keep the device on
im trying to do somekind of auto GoogleDrive backup(uploading a file) timer, but i cant set the specific time, even if i set to 5 seconds(testing purpouse, it just run every 1minute) and when the user reboot the phone, it only RUN one time (the Alarm is not called =/, so the application has to be opened one time after the boot)
Manifest Configuration:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application...>
<receiver
android:name=".Tools.AutoBackupAlarmBroadCast"
android:process=":remote" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".Tools.AutoBackupService"
android:exported="false" />
</application>
and with this WakeBroadCast:
public class AutoBackupBootStarter extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, AutoBackupService.class);
context.startService(startServiceIntent);
}
}
make sure that the AutoBackupAlarm is called on boot, but it only happens ONE time, i need it to start the trigger to repeat by the user setted time(will get it from shared Preferences)
the service:
AutoBackupService:
public class AutoBackupService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
*/
public AutoBackupService() {
super("AutoBackup");
}
#Override
protected void onHandleIntent(Intent intent) {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
//HERE i must start the Async to make the GoogleDrive Backup
//the next doubt will be how can i get sharedpreferences and activity to pass to the async from HERE?
Log.d("BACKUP", "AutoBackupLogTest");
}
}
the broadcast
public class AutoBackupAlarmBroadCast extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AutoBackupService.class);
i.putExtra("foo", "bar");
context.startService(i);
}
}
the AlarmFunction called on onCreate, that almost works how i want, it cant repeat every 5 seconds like the time below, it only show every 1 minute
public void scheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), AutoBackupAlarmBroadCast.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, AutoBackupAlarmBroadCast.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
// Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
1 * 5 * 1000, pIntent);
}
Try below code to repeat task after particular time interval
boolean alarmUp = (PendingIntent.getBroadcast(this, 444, new Intent(this, AlarmReceiver.class), PendingIntent.FLAG_NO_CREATE) != null);
if(!alarmUp){
AlarmManager alarmManager = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent DataSyncIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 444, DataSyncIntent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(),
15 * 60000, // 60000 = 1 minute,
pendingIntent);
}
My apps alarm fires directly after each reboot, not at the specified time and it's not repeating. The alarm I set is ignored.
InitializeAlarm:
public class InitialisiereAlarm extends Activity {
private static final String TAG = "InitialisiereAlarm";
private static AlarmManager am;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
aktiviereAlarmDownload();
finish();
}
private void aktiviereAlarmDownload() {
Calendar calAkt = Calendar.getInstance();
calAkt.setTimeInMillis(System.currentTimeMillis());
calAkt.set(Calendar.DAY_OF_WEEK, 2);
calAkt.set(Calendar.HOUR_OF_DAY, 10);
calAkt.set(Calendar.MINUTE, 15);
Intent intent = new Intent(this, StartAlarm.class);
intent.putExtra("alarmCode", "12345");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12345,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calAkt.getTimeInMillis(),
AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
}
StartAlarm extends BroadcastReceiver, actually the same plus starting another activity:
public class StartAlarm extends BroadcastReceiver {
private static final String TAG = "StartAlarm";
private WakeLock wl;
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context
.getSystemService(Activity.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SomeTag");
wl.acquire();
Intent intent2 = new Intent();
intent2.setClassName("com.test.testApp",
"com.test.testApp.DoThings");
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent2);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 12345,
intent2, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calAkt = Calendar.getInstance();
calAkt.setTimeInMillis(System.currentTimeMillis());
calAkt.set(Calendar.DAY_OF_WEEK, 2);
calAkt.set(Calendar.HOUR_OF_DAY, 10);
calAkt.set(Calendar.MINUTE, 15);
AlarmManager am = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calAkt.getTimeInMillis(),
AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
StartAlarm in the Manifest:
<receiver
android:name=".timer.StartAlarm"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I don't see what I'm doing wrong. Guess there's something I didn't understand... Any help is apprechiated!
Edit:
The problem was, that the alarm layed in the past. Solved it by setting the alarm to a future date by inserting
Calendar cal = Calendar.getInstance();
if (calAkt.compareTo(cal) <= 0) {
calAkt.add(Calendar.MINUTE, 8);
}
Thanks #CommonsWare for the hint
My apps alarm fires directly after each reboot
No, it does not. However, your StartAlarm BroadcastReceiver is getting control at boot time, because that is what you put in your manifest. If you do not want StartAlarm to get control at boot time, then get rid of its <intent-filter> in the manifest.
I am trying to create a notification at a particular time. Im creating a broadcast receiver and calling it through the AlarmManager. Problem is that the broadcast is not received and that I am not getting any notifications.
Registering the Broadcast Receiver in the Manifest,
<receiver
android:name="com.example.android.receivers">
<intent-filter>
<action android:name="com.example.android.receivers.AlarmReceiver" />
</intent-filter>
</receiver>
This is the Broadcast Receiver,
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context pContext, Intent pIntent) {
// if (pIntent.getAction().equalsIgnoreCase("")) {
//
// }
Log.d("Alarm Receiver", "onReceive called");
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(pContext).setSmallIcon(R.drawable.icon).setContentTitle("Test Notification")
.setContentText("Test Notification made by Syed Ahmed Hussain");
Intent resultIntent = new Intent(pContext, CalendarView.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(pContext);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(CalendarView.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) pContext.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notificationBuilder.build());
}
}
Code from Main Activity which creates an Alarm.
/**
*
* #param pDate
* #param pTime
*/
private void createNotification(String pDate, String pTime) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
// alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), alarmIntent);
}
Can anyone please point out and rectify what am I doing wrong? Thank you.
You have a wrong definition of the Receiver in your Manifest.
Try this:
<receiver android:name="com.example.android.receivers.AlarmReceiver" />
in android:name you have to specify the absolute package+class of the receiver, or the relative from the package="com.example.android" you specified in the root element of the Manifest. e.g:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android" >
Action sections of receivers are to specify which actions to listen. So you can also do it this way:
Create an Intent based on the Action instead of the class
public static final String ACTION = "com.example.android.receivers.NOTIFICATION_ALARM";
private void createNotification(String pDate, String pTime) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ACTION);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), alarmIntent);
}
Then you can handle multiple actions in your receiver:
#Override
public void onReceive(Context pContext, Intent pIntent){
if (pIntent.getAction().equals(ACTION)){
// Here your handle code
}
}
But then, you will have to declare your receiver in the manifest this way:
<receiver android:name="com.example.android.receivers">
<intent-filter>
<action android:name="com.example.android.receivers.NOTIFICATION_ALARM" />
</intent-filter>
</receiver>
You can use both ways.
I am working on an application inwhich I am using AlarmManager for scheduling things. My Alarm is set. But this Alarm does not invoke BroadcastReceiver written to catch the event. I have searched a great deal but I have not found anything that solves the issue. I am posting my code, please have a look and see if I am missing something.
AlarmManagerClass:
public class ScheduleMessageManager {
Context context;
PendingIntent sender;
AlarmManager am;
public ScheduleMessageManager(Context context) {
this.context = context;
}
public void addAlram(int scheduledMessageID, long scheduledTime) {
// Activate Broadcast Receiver to receive broadcasts
activateBroadcastReceiver();
//Calendar cal = Calendar.getInstance();
Intent intent = new Intent(context, AlarmReceiver.class);
// In reality, you would want to have a unique variable for the request
// code
intent.putExtra("scheduledMessageID", scheduledMessageID);
sender = PendingIntent.getBroadcast(context, scheduledMessageID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
am = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, scheduledTime, sender);
Log.e("In ScheduleMessageManage", "***** Alarm is set to the mmessage *****");
}
public void cancelPeriodicSchedule(PendingIntent sender) {
if (am != null) {
if (sender != null) {
am.cancel(sender);
sender.cancel();
}
}
// Deactivate Broadcast Receiver to stop receiving broadcasts
deactivateBroadcastreceiver();
}
private void activateBroadcastReceiver() {
PackageManager pm = context.getPackageManager();
ComponentName componentName = new ComponentName(context, AlarmReceiver.class);
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Toast.makeText(context, "activated", Toast.LENGTH_LONG).show();
}
private void deactivateBroadcastreceiver() {
// TODO Auto-generated method stub
PackageManager pm = context.getPackageManager();
ComponentName componentName = new ComponentName(context, AlarmReceiver.class);
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Toast.makeText(context, "cancelled", Toast.LENGTH_LONG).show();
}
}
My AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
int pendingIntentID; // same as scheduledMessageID
#Override
public void onReceive(Context context, Intent intent) {
Log.e("In On Receive", "Alarm has Initiated Broadcast Receiver....");
if (intent.hasExtra("scheduledMessageID")) {
pendingIntentID = intent.getExtras().getInt("scheduledMessageID");
Intent sendMessageServiceIntent = new Intent(context, SendMessageService.class);
sendMessageServiceIntent.putExtra("pendingIntentID", pendingIntentID);
context.startService(sendMessageServiceIntent);
}
}
}
OnReceieve() is never called.
In My Manifest.xml
<receiver
android:name="myPackage.AlarmReceiver"
android:enabled="true" >
</receiver>
I am unable to figure out the does the problem lie. Please help me out of it. Thanks.!
A good tutorial on using Broadcast receivers is given in http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html. In essence, your receiver doesn't declare what events it will receive. The declaration in the Manifest file needs something like:
<receiver
android:name="myPackage.AlarmReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="your.company.blah.mybroadcast" />
</intent-filter>
</receiver>
And when you create the intent, it needs
Intent intent = new Intent();
intent.setAction("your.company.blah.mybroadcast");
// All the other things you want to put in the intent
I know that this has been answered already, but just for further reference as I ran into the same issue, make sure that your receiver tags are inside the tags, but not inside any other tag such as activity (that's exactly the issue I had).
Also it helps a great deal to check that your alarm has been successfully registered, to so run:
adb shell dumpsys alarm
You just need to registered your receiver with alarm manager this will call broadcast after every 60 second:
Intent broadcastIntent = new Intent(YourActivity.this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, broadcastIntent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
long timeInterval = 60 * 1000;
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), timeInterval, pi);
In Manifest:
<receiver
android:name="myPackage.AlarmReceiver"
android:enabled="true" >
</receiver>