Android AlarmManager.setExactAndAllowWhileIdle() and WakefulBroadcastReceiver Not working in some new manufactured and low price devices
Asked Answered
F

4

28

I think this question is asked many time in stackoverflow but still so many people struggling to resolved it.

In my android app I have to wake up device for every half hour to getting current location and send it to server. For this I have used AlarmManager with setExactAndAllowWhileIdle() method and WakefulBroadcastReceiver. Its working fine in almost all standard/popular devices like samsung, LG(Nexus), Sony, Panasonic, lenovo, Motorola, Micro max and so on....But some other devices mostly china devices not supporting or cannot allow device wake up from doze mode with setExactAndAllowWhileIdle(). I have tested it in leeco letV (Android OS 6.1) device which not allow alarm manager to wake up in specific interval.

My code portion I have mentioned below :

UserTrackingReceiverIntentService.java

public class UserTrackingReceiverIntentService extends IntentService {

    public static final String TAG = "UserTrackingReceiverIntentService";
    Context context;
    public UserTrackingReceiverIntentService() {
        super("UserTrackingReceiverIntentService");
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onHandleIntent(Intent intent) {
        this.context = this;

        if (!Util.isMyServiceRunning(LocationService.class, context)) {
            context.startService(new Intent(context, LocationService.class));
        }

        Calendar calendar = Calendar.getInstance();
        //********************************** SETTING NEXT ALARM *********************************************
            Intent intentWakeFullBroacastReceiver = new Intent(context, SimpleWakefulReceiver.class);
            PendingIntent sender = PendingIntent.getBroadcast(context, 1001, intentWakeFullBroacastReceiver, 0);
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);

        if (calendar.get(Calendar.MINUTE) >= 0 && calendar.get(Calendar.MINUTE) < 30) {
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
            calendar.set(Calendar.MINUTE, 30);
            calendar.set(Calendar.SECOND, 0);
        } else if (calendar.get(Calendar.MINUTE) >= 30) {
            if (calendar.get(Calendar.HOUR_OF_DAY) == 23) {
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            } else {
                calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1);
            }
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        } else {
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        }

        //MARSHMALLOW OR ABOVE
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
                    calendar.getTimeInMillis(), sender);
        }
        //LOLLIPOP 21 OR ABOVE
        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(calendar.getTimeInMillis(), sender);
            alarmManager.setAlarmClock(alarmClockInfo, sender);
        }
        //KITKAT 19 OR ABOVE
        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP,
                    calendar.getTimeInMillis(), sender);
        }
        //FOR BELOW KITKAT ALL DEVICES
        else {
            alarmManager.set(AlarmManager.RTC_WAKEUP,
                    calendar.getTimeInMillis(), sender);
        }


        Util.registerHeartbeatReceiver(context);
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }
}

Every time above service set next alarm after 30 min once it called.

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Calendar calendar = Calendar.getInstance();
        Intent service = new Intent(context, UserTrackingReceiverIntentService.class);
        Date date = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        String DateTime = sdf.format(date);
        DateTime = Util.locatToUTC(DateTime);
        service.putExtra("date", String.valueOf(DateTime));

        String latitude = Util.ReadSharePrefrence(context, "track_lat");
        String longitude = Util.ReadSharePrefrence(context, "track_lng");

        service.putExtra("lat", latitude);
        service.putExtra("lon", longitude);

        Log.i("SimpleWakefulReceiver", "Starting service @ " + calendar.get(Calendar.HOUR_OF_DAY) + " : " + calendar.get(Calendar.MINUTE) + " : " + calendar.get(Calendar.SECOND));

        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, service);
    }
}

As I have changed some setting manually from leeco letV device like Settings > Battery > Align Wakeup > Disabled both the options. If it enabled battery can ignore force wake ups from apps.

My Questions:

  1. What happened in such kind of devices? Why they not allow alarm to fire in specific time interval?

  2. In some devices like Gionee s plus alarm firing 2-3 minutes late... why?

  3. android.net.conn.CONNECTIVITY_CHANGE broad cast receiver to listen when network connectivity change .....What to do when it is not working in some devices like Gionee s plus?

  4. There are many variation for battery optimization setting for various manufacturer....Is it can harm to our app's background services if is then what the solution for this.

Folberth answered 2/12, 2016 at 12:12 Comment(5)
Could you take a look at my question here https://mcmap.net/q/504849/-broadcastreceiver-doesnt-work-if-i-close-recent-apps/6852390...and Help Me if You canMaurinemaurise
For example on Huawei devices, you hace to enable AutoStart, otherwise it´s not possible to send Broadcasts. On HuaweiAscend Mate 7, there is a TelephonyManager with the option Auto Start where all apps are listed. Maybe on some of your tested devices have a similar manager.Nodal
@himCream I am currently checking with this lib github.com/evernote/android-job , hope it will help somehow.!! lets see.Saveall
I also started getting doubts that this issue will be solved by ... Not Using Alarm Manager for Higher version of android and start using JobScheduler for android M.Saveall
@ MKJParekh I have studied about JobScheduler its cool but I want waking up device every half hour and I read that you we cant keep running JobScheduler in Deze mode in Android M and N.....However have have already so many devices with alarm feature and they are working fine ......but some new manufactured device with china companies are not allow to firing alarm in specific interval.....setExactAndAllowWhileIdle() this method working awesome in Doze mode.....but concern is only for some devices ......thanks for you great support.....Folberth
C
3

Hi I have got same issue while testing in Xiomi phone.leeco I haven't much idea. Xiomi phone have their own OS that is MIUI.When we cleared RAM it clear all the apps execpt some of apps register in OS. Like Whatsapp and facebook some other famous apps.

I have tried Service, Alarm Manager and Scheduler but not get any success.

They provide some manually specfic way to run services.I have checked Leeco it used Android OS.

Solution for MIUI 7.0 => Security => Autostart => select Apps that you want to run in background => Reboot After reboot your device should able to run your application services in background like other android devices do.

MIUI 4.0 settings

MIUI AutoStart Detailed Description

According to me you can try with Services then check if it work or not.

Thanks hopefully you'll get bit help from this.

Coper answered 12/12, 2016 at 13:53 Comment(5)
I found this setting in Xiomi phone but I don,t know that Leeco has the same setting or not.....Does Leeco phone has these settings?Folberth
@himCream i'm also not sure. You can try with services. It might help you.Coper
take a look from here blog.hypertrack.io/2016/12/01/…Coper
thank you very very much for your valuable answer and comments.....but I have already seen the link that you send me here....I am already using alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender); but still in some marshmellow devices alarms are missing and one more thing i noticed in gionee device that alarm firing by 2 -3 min late......have faced these types of issues ?Folberth
Yes it happened due to they customize OSCoper
S
3

In my android app I have to wake up device for every 15 min to getting current location and send it to server. Application flow diagram I have tested it on Xiaomi Mi 5s (Android 6.0.1). When I close the application, the application goes to sleep :( AlarmManager with setExactAndAllowWhileIdle() not working ¯\_(ツ)_/¯

Yes, it's working fine in almost all standard/popular devices like Samsung, LG (Nexus 5X), Sony, Motorola, Pixel...

MY SOLUTION:

The manifest entry for each type of component element — <activity>, <service>, <receiver>, and <provider> — supports an android:process attribute that can specify a process in which that component should run.

You need add this string android:process=":service" in your AndroidManifest.xml

Like this:

... 

<receiver
    android:name="your.full.packagename.MyWakefulReceiver"
    android:process=":service"
    android:enabled="true"/>

<service
    android:name="your.full.packagename.MyLocationService"
    android:process=":service"/>

<service
    android:name="your.full.packagename.MySendService"
    android:process=":service"
    android:exported="false" />

...

I have tested this solution on Xiaomi Mi 5s. It's work !!!

IMHO it seems that the Xiaomi firmware kills the main process whenever the user exits the application...

Suprasegmental answered 4/9, 2017 at 19:28 Comment(3)
Thank you for above ans...Xiaomi, Oppo and vivo mobile have its own ROM, in these devices, once you leave your app from foreground, its kills all background services and apps. For resolving this problem temporarily I have found a solution, ---> You need to lock your app in background, I did search many time but I dint find anything, Do you have any other solution if one don't want to keep lock app in background specially in Xiaomi , oppo and vivo .............. ???Folberth
1) When i don't use android:process=":service" Xiaomi kill my AlarmManager immediately after leaving MainActivity. 2) When i use android:process=":service" as shown in the diagram above Xiaomi kill my AlarmManager some time later. "You need to lock your app in background" ? @himCream what did you mean?Suprasegmental
"You need to lock your app in background" that mean in 'Recent app list' you have to lock your app. like this softwarert.com/lock-background-apps-xiaomi-redmi-phones ...............Folberth
G
2

Probably these Chinese phones have disabled app wake for receiving alarm events to conserve battery life. I know that some Chinese makers don't wake app to receive push notifications if they are closed for battery conservation earlier. Thus until the app is manually opened again, it will not be woken up by the OS for any event processing.

However this behaviour can be changed. Check power management settings and change accordingly to allow apps to be woken up at regular intervals or when needed. I think it could be Restricted Mode or something similar.

Garzon answered 12/12, 2016 at 18:53 Comment(2)
....you are right recently I have checked in one MI phone they are using MIUI and I have to give manually auto start permission for running my app in background.....but I have seen whatsapp and facebook and some other brands app are already there without manually enter them into auto run permission.....what may they are doing for adding the app in auto start permission?Folberth
@himCream Popular apps like Facebook, WhatsApp and Gmail are by default whitelisted at the OS level. They really don't have to do anything to make it work.Marylyn
M
1

I agree with you. But I think you should try with JobScheduler once. You will find official documentation https://developer.android.com/reference/android/app/job/JobScheduler.html Best example I find https://github.com/googlesamples/android-JobScheduler I don't have test it.according to me you have to try this.

EDIT

If you want to run your application in doze mode in 6.0 or later, you have to white list your application check out

https://www.bignerdranch.com/blog/diving-into-doze-mode-for-developers/

https://developer.android.com/training/monitoring-device-state/doze-standby.html

Imtiyaz

Michaelis answered 13/12, 2016 at 5:9 Comment(3)
Thank you for giving me a way....I am really exiting to implementing job scheduler but can job scheduler run in doze mode or deep doze mode in Android OS 6 and 7 ?Folberth
@himCream I have Update my answer.Michaelis
@Imtiyaz...thank you for your answer.....but I have seen above two links which give a great understanding about doze. I already have used a alarm manage with method setExactAndAllowWhileIdle() for marshmellow and above.....but my question is still in some devices alarm missing......and in gionee device alarm fire 2 to 3 min late than specific time interval.....please check my question and above code....if you want I can give you further information according to my function and code....Folberth

© 2022 - 2024 — McMap. All rights reserved.