I am using the following code to start a service periodically whether the app is foreground or not .
Intent getAlertIntent = new Intent(getApplicationContext(), GetAlertAlarmReceiver.class);
PendingIntent getAlertpendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, getAlertIntent, 0);
AlarmManager getAlertmanager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
getAlertmanager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, getAlertpendingIntent);
The code for my receiver is following
public class GetAlertAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, GetAlertServiceIntent.class);
context.startService(i);
}
}
And and service
public class GetAlertServiceIntent extends IntentService {
public GetAlertServiceIntent() {
super("GetAlertServiceIntent");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(Intent intent) {
doSomething();
}
}
In my manifest file I declared everything as following
<receiver
android:name=".broadcastreceiver.GetAlertAlarmReceiver"
android:enabled="true">
<intent-filter android:priority="999">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="com.surroundapps.shotorkoporibar.services.GetAlertServiceIntent" />
This code work as expected in API level below Marshmallow but in marshmallow it doesn't work .
Related
I have an Activity that is supposed to launch a Service via a BroadcastReceiver.
Overview of the three:
Activity = Tracking
Service = PhoneManagementService
BroadcastReceiver = TrackingRestart
The Activity launches the AlarmManager in the onCreate() method:
public class Tracking extends Activity {
private static final int ALARM_FREQUENCY_SECONDS = 60;
#Override
protected void onCreate(Bundle savedInstanceState) {
startService(new Intent(Tracking.this, PhoneManagementService.class));
Intent alarm = new Intent(this, TrackingRestart.class);
boolean alarmRunning = (PendingIntent.getBroadcast(this, 0, alarm, PendingIntent.FLAG_NO_CREATE) != null);
if(!alarmRunning) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), (ALARM_FREQUENCY_SECONDS * 1000), pendingIntent);
}
}
I included startService(new Intent(Tracking.this, PhoneManagementService.class)); in there because this is the only time that the Service is called.
The BroadcastReceiver looks like this:
public class TrackingRestart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, PhoneManagementService.class));
context.stopService(new Intent(context, PhoneManagementService.class));
}
}
The Service class looks like this:
public class PhoneManagementService extends Service {
private String user = "Service";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onCreate() {
startForeground(NotificationCreator.getNotificationId(), NotificationCreator.getNotification(this));
DBAdapter newEntry = new DBAdapter(this);
newEntry.open();
newEntry.addEntry("charging", user, getChargerType());
newEntry.addEntry("battery", user, getBatteryStats());
newEntry.addEntry("network", user, getNetworkType());
newEntry.close();
}
}
The Manifest containts those three entries:
<activity android:name=".Tracking">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".GPSService"
android:process=":trackingService_gps"
android:launchMode="singleTop"
android:enabled="true" />
<service
android:name=".PhoneManagementService"
android:process=":trackingService_phoneManagement"
android:launchMode="singleTop"
android:enabled="true" />
<receiver
android:name=".TrackingRestart"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="ch.jpabig.jonastrackingapp.ActivityRecognition.RestartTracking"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
<action android:name="android.intent.action.BATTERY_LOW"/>
<action android:name="android.intent.action.BATTERY_OKAY"/>
</intent-filter>
</receiver>
Somehow the entries into the database are not made and I'm at a lost why this is the case. It must be the alarm but I could be very wrong.
I can't seem these to get up and running:
public class BackgroundSyncService extends IntentService {
public BackgroundSyncService() {
super("SchedulingService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i("asd-service", "lol");
BackgroundSyncBroadcastReceiver.completeWakefulIntent(intent);
}
}
Second class:
public class BackgroundSyncBroadcastReceiver extends WakefulBroadcastReceiver {
private AlarmManager alarmManager;
private PendingIntent alarmIntent;
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, BackgroundSyncService.class);
startWakefulService(context, service);
}
public void setAlarm(Context context){
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, BackgroundSyncBroadcastReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
0, 5000, alarmIntent);
ComponentName receiver = new ComponentName(context, BackgroundSyncBroadcastReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
}
Third class:
public class BackgroundSyncBootReceiver extends BroadcastReceiver {
BackgroundSyncBroadcastReceiver service = new BackgroundSyncBroadcastReceiver();
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
service.setAlarm(context);
}
}
}
Manifest.xml:
<receiver android:name=".BackgroundSyncBroadcastReceiver"/>
<receiver android:name=".BackgroundSyncBootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name=".BackgroundSyncService"/>
Your receiver for BOOT_COMPLETED will not be allowed to fire until your app has been manually started by the user one time. This is a security feature to prevent apps from running without the user knowing about them.
So, yeah, I forgot to start it from the acivity...
BackgroundSyncBroadcastReceiver service = new BackgroundSyncBroadcastReceiver();
service.setAlarm(this);
Stupid mistake.
I have an AlarmReceiver with an AlarmService and my problem is, if I set the AlertDate about 30min away from the current time, it just does it's job and calls the Alert-function. But if I set it about 5hours away, it won't call the function, no matter if I do it at night (not using my phone) or at day (while my phone is in use).
So my question is, why can't I set the AlertDate in the "far" future? Is the process killed or is there anything strange happening? And in particular: How can I fix this problem??
Basically I have the arrangement from here: Android Alarm Clock Tutorial
So I just point out my main lines in the code:
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="apm.smoothalert" >
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
...
<application
...
<activity
android:name=".main"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".AlarmService"
android:enabled="true" />
<receiver android:name=".AlarmReceiver" />
</application>
main:
public class main extends ActionBarActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
PowerManager powman = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powman.newWakeLock(PowerManager.FULL_WAKE_LOCK,"MyWakelockTag");
wakeLock.acquire();
...
}
AlarmManager alarmManager;
private PendingIntent pendingIntent;
private void smoothAlertOn ()
{
Date AlertDate = ... ; //Here I select the Alert date with a Timepicker
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(main.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(main.this, 0, myIntent, 0);
alarmManager.set(AlarmManager.RTC, AlertDate.getTime(), pendingIntent);
}
public static void SmoothAlert(final Context context)
{
//Here i do the Alert with Notifications etc.
}
}
AlarmReceiver:
public class AlarmReceiver extends WakefulBroadcastReceiver
{
static Context Alarmcontext;
#Override
public void onReceive(final Context context, Intent intent)
{
Alarmcontext = context;
ComponentName comp = new ComponentName(context.getPackageName(),AlarmService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
AlarmService:
public class AlarmService extends IntentService
{
public AlarmService()
{
super("AlarmService");
}
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public void onHandleIntent(Intent intent)
{
main.SmoothAlert(AlarmReceiver.Alarmcontext);
}
}
Strange issue, my app has tens of thousands of users, for most of them this works perfectly. Some, let's say 5%, experience issue that causes reminders to not be fired.
I've put logging on the scheduling mechanism, including the scheduled timestamp, so I know that the reminder was scheduled, but it AlarmReceiver wasn't called.
Why would AlarmManager sometimes not fire?
ReminderLogic.java -
public class ReminderLogic {
public static void schedule() {
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
int timeMillis = ... // some calculation
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeMillis, alarmIntent);
else
alarmManager.set(AlarmManager.RTC_WAKEUP, timeMillis, alarmIntent);
}
}
AlarmReceiver.java -
public class AlarmReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, AlarmService.class);
startWakefulService(context, service);
}
}
AlarmService.java -
public class AlarmService extends IntentService {
private final static String TAG = "AlarmService";
public AlarmService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
ReminderLogic.schedule();
AlarmReceiver.completeWakefulIntent(intent);
}
}
BootReceiver.java -
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ReminderLogic.schedule();
}
}
PackageReplaceReceiver.java -
public class PackageReplaceReceiver extends BroadcastReceiver {
private static final String TAG = "BootReceiver";
#Override
public void onReceive(Context context, Intent intent) {
ReminderLogic.schedule();
}
}
AndroidManifest.xml -
<service android:name=".reminders.AlarmService" />
<receiver android:name=".reminders.AlarmReceiver" />
<receiver
android:name=".reminders.BootReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".reminders.PackageReplaceReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Why my AlarmManager for service update doesn't work? this is my code:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService();
}
// Method to start the service
public void startService() {
startService(new Intent(getBaseContext(), MyService.class));
}
// Method to stop the service
public void stopService() {
stopService(new Intent(getBaseContext(), MyService.class));
}
Service class:
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onCreate() {
poruka();
super.onCreate();
}
public void poruka(){
Toast.makeText(this, "OnCreate work!", Toast.LENGTH_LONG).show();
}
}
BroadcastReceiver and AlarmManager:
public class ServiceBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, MyService.class));
Intent alarmIntent = new Intent(context, ServiceBroadcast.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, Calendar.getInstance().getTimeInMillis(), 30*1000, pendingIntent);
}
}
And Permissions:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="me.example.nservice.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService" android:enabled="true"
android:label="Servisv1" />
<receiver android:name="me.example.rqservice.ServiceBroadcast" android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
I receive message "OnCreate work!" and "Service Started" only first time when i open app. Why update doesn't work every 30 sec?
To start a service every 30 seconds :
Inside onCreate() :
Here MyService is the name of the Service.
Intent myService = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(
this, 0, myService, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 30*1000,pendingIntent);
This'll start your service every 30 seconds. However, if the service is already running, which might be the case once it has been started the first time, from next time onwards the call will directly go to onStartCommand() method of the Service and not onCreate().
This is all that you need to do. However, if you want to make sure that the AlarmManager keeps restarting the service even after a phone is restarted, you'll need to add a BroadcastReceiver for Boot.