How to run the background service in Android O, every minute? - android

I have an old application in which the service was invoked using the AlarmManager's setExact every minute, but in the latest Android O, it is not allowing me to run the service in the same way. I couldn't use foreground service because I don't want to show any notification when my service is running.
I want help on tweaking my application architecture in a way so that my code should run in the Android O with minimum changes.
When I run my application in the Android, it is crash:(.Please find the stack trace of the crash below.
java.lang.RuntimeException: Unable to create application com.***.***.***ControllerApplication: java.lang.IllegalStateException: Not allowed to start service Intent
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.***.***.qa/com.***.***.services.AlarmService
Edit:
The task in my application is time critical therefore I used setExact in AlarmManager but none of the currently supported APIs is scheduling jobs at an exact time. With that said, If I use JobScheduler/ WorkManager then my application will malfunction.

You can use the Alarm manager which will be called after every 10 mins
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Random random = new Random();
int m = random.nextInt(9999 - 1000) + 1000;
Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
notificationIntent.setClass(this,AlarmReceiver_.class);
notificationIntent.addCategory("android.intent.category.DEFAULT");
PendingIntent broadcast = PendingIntent.getBroadcast(YourClass.this, r5, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 300000L,
600000L, broadcast);
ManiFest receiver Code where you will get a receiver response
<receiver android:name="com.yourpackage.AlarmReceiver_"
>
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.REBOOT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
You will have to create Receiver where you will receive data as an above-specified name of AlarmReceiver_.class

Related

setAlarmClock not work when set from reciever

In my code I have a broadcast reciever
<receiver
android:name=".alarm.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
<intent-filter>
<action android:name="com.BalDroid.YekNegah.alarm.dailyAction"
/>
</intent-filter>
</receiver>
I schedule alarm in this receiver in onReceive method
PendingIntent pi = PendingIntent.getBroadcast(context, AlarmRow.getId(mycursor), i, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= 21) {
AlarmManager.AlarmClockInfo alarmInfo = new AlarmManager.AlarmClockInfo(
mycal.getTimeInMillis(),pi);
mgr.setAlarmClock(alarmInfo,pi);
// Create a Pending intent to show Alarm Details
}
although receiver run but alarm not trigger with mgr.setAlarmClock. But when I use
mgr.setExactAndAllowWhileIdle alarm trigger
(because of setAlarmClock accuracy I have to use setAlarmClock in my code)
And when I schedule mgr.setAlarmClock from MainActivity (when start application manually) it works.
I cant find the solution!!.
(I don't know why is not work from receiver).
My app also called setAlarmClock on AlarmManager, however the event didn't trigger. The reason for me was the default restriction of background processes by the manufacturer(my phone is Xiaomi).
Go to Settings -> Your application and find background restriction options. Turn the restrictions off and setAlarmClock must work.
As a conclusion, the result depends on manufacturer's default settings.

Use Alarm Manager to set Notification at specific time but my receiver class is not called on time

Long time = prefs.getLong("dailynoti", 0);
Intent intent = new Intent(cn, NotificationReceiver.class);
intent.putExtra("Desc", "Description...");
PendingIntent pendingIntent = PendingIntent.getBroadcast(cn, 1055, intent,0);
AlarmManager alarmManager = (AlarmManager) cn.getSystemService(cn.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,time, AlarmManager.INTERVAL_DAY, pendingIntent);
and my mainifest file
<receiver
android:name="com.mypackage.NotificationReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.REBOOT" />
<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>
And this same code is use in same project but now in same project another module it will not work Broadcast Receiver isn't call at given time
my notification code is in Receiver file but Receiver class isn't call.
I checked all things like time is also get properly. so what is the problem . please help...
I used many solution like
PendingIntent pendingIntent = PendingIntent.getBroadcast(cn, 1055, intent, PendingIntent.FLAG_CANCEL_CURRENT
//FLAG_NO_CREATE
//FLAG_UPDATE_CURRENT
One approach that I think that will work is instead of alarmManager.setRepeating() use alarmManager.set() and when the alarm triggers then set the next alarm. This will give you almost accurate results. Why almost? Because due to Doze mode introduced in Android M. So this will give you between 0 to +5 min delay.

Alarmmanager not firing first alarm if device is off

I am using alarm manger to set broadcast on 2am every day. Alarm manager working fine in normal scenarios but it failing in below scenario.
I am scheduling alarm manager #1am, change the time to 1.58am and switch off the device and switch on the phone after 5mins(i.e 2.03am). In this scenario my alarm is not triggering for same day and every other days.
Can some one help me with this scenario
//Alarm manager
//timeToTwoAm is calculate time to 2AM from current time
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,timeToTwoAm,
AlarmManager.INTERVAL_DAY, alarmIntent);
Your alarms will not be persisted. After a reboot all your registered alarms are removed.
2 solutions would be helpful:
1. Register a BOOT_COMPLETED broadcast receiver:
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".notification.alarm.OnBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And in your OnBootReceiver simply register your alarms at AlarmManager again.
2. Use JobScheduler-API (>= API 21) or GcmNetworkManager (PlayServices)
Depending on your use case it would also be possible to use the new GcmNetworkMaanger, which allows persisting a Job during reboot.
Add Service to your Manifest:
<service
android:name=".LoadWeatherService"
android:exported="true" android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
<intent-filter>
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
</intent-filter>
</service>
In your service declare the things to do:
public class LoadWeatherService extends GcmTaskService {
public void onInitializeTasks() {
super.onInitializeTasks();
// Reregister your Job after update of Google Play Services
}
#Override
public int onRunTask(TaskParams taskParams) {
// Do your stuff
return GcmNetworkManager.RESULT_SUCCESS;
}
}
Subscribe your Job
String tag = "myperiodicTask";
PeriodicTask periodicTask = new PeriodicTask.Builder().setService(LoadWeatherService.class)
.setRequiredNetwork(Task.NETWORK_STATE_CONNECTED).setPeriod(60L).setFlex(10L)
.setTag(tag).setPersisted(true).build();
GcmNetworkManager.getInstance(this).schedule(periodicTask);
Please notice: This is only a sample from my app, you have to adjust this regarding your needs.
Further Reading about GcmNetworkManager: https://developers.google.com/cloud-messaging/network-manager

Broadcast receiver not exceuted on application force close

I have an application developed for jelly bean, where I schedule an event to be executed in the future using Alarm manager. The scheduled event executes as expected as long as the application runs in the foreground or in the background. But once I force close the application under taskmanager, I am no longer able to receive the broadcast from the alarm manager.
As suggested by various posts and blogs i tried using Intent.Flag_Include_Stopped_Packages. But it was of no use. Including this flag in the intent works only for sendBroadcast(intent). But in case of an alarm manager where pending intent is used,it does not work.
My code to schedule the alarm
Intent intent = new Intent("com.dummy.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(),dummyId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, scheduledAlarm.getTimeInMillis(), pi);
My mainfest
<receiver android:name="com.example.androidScheduling.alarmReceiver"
android:enabled="true"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="com.dummy.intent"></action>
</intent-filter>
</receiver>
Can someone please help me out?
I even tried including android:process = ":remote" for the receiver in manifest. But even that did not help.
I think you have not spelled correctly the intent's action name in manifest and programmatically .
In pro-grammatically
Intent intent = new Intent("com.dummy.intent");
Manifest file-
<intent-filter>
<action android:name="com.custom.intent"></action>
</intent-filter>
The action name to intent and declared in manifest must require same.
Hope this helpful to you

Broadcast receiver distinguishing call reason based on action name of intent

I am having a problem with my application's broadcast receiver.
I have a situation where I wan the broadcast receiver to be called for 3 different reasons, first phone state changed, second, based on a timer, and third on boot complete. And then according to the reason by which the broadcast receiver was called I want to be able to do some stuff.
below is my android manifest of my receiver:
<receiver android:name="com.example.mobileraptor.MyPhoneListener" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="com.example.mobileraptor.TimerTriggered" />
</intent-filter>
</receiver>
and the following is where i declare my TimerTriggered intent:
PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent("com.example.mobileraptor.TimerTriggered"), 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
manager.setInexactRepeating( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), AlarmManager.INTERVAL_HOUR , pintent );
The problem is that once the application wants to boot it crashes. but if I comment the line :
action android:name="com.example.mobileraptor.TimerTriggered
then my application is fine.
what is wrong with the action name that I have defined.

Categories

Resources