提问者:小点点

Android警报管理器. setExactAndAllowWhileIdle()和WakefulBroadcastRec不工作在一些新的制造和低价格设备


我认为这个问题在stackoverflow中被问了很多次,但仍然有很多人在努力解决它。

在我的android应用程序中,我必须每半小时唤醒设备以获取当前位置并将其发送到服务器。为此,我使用了警报管理器setExactAndAllowWhileIdle()方法和WakefulBroadcastReccher。它在几乎所有标准/流行的设备中都能正常工作,如三星、LG(Nexus)、索尼、松下、联想、摩托罗拉、Micro max等……但其他一些设备大多是中国设备,不支持或不允许设备从打瞌睡模式中唤醒,使用setExactAndAllowWhileIdle()。我已经在leeco letV(AndroidOS6.1)设备中测试过了,该设备不允许警报管理器在特定间隔内唤醒。

我在下面提到的代码部分:

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);
    }
}

每次以上服务设置下一次报警后30分钟一次调用。

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);
    }
}

因为我已经从leeco letV设备手动更改了一些设置,例如设置

我的问题:

>

  • 这种设备发生了什么?为什么他们不允许警报在特定的时间间隔内触发?

    在某些设备中,如金立的plus报警器延迟2-3分钟点火…为什么?

    android.net. conn.CONNECTIVITY_CHANGE广角接收器,用于在网络连接发生变化时收听………当它在某些设备(如Gionee s plus)中不工作时该怎么办?

    不同制造商的电池优化设置有很多变化……如果是解决方案,它会损害我们应用程序的后台服务吗?


  • 共3个答案

    匿名用户

    嗨,我有同样的问题,而测试在小米手机. leeco我没有太多的想法.小米手机有自己的OS那就是MIUI.当我们清除RAM它清除所有的应用程序执行一些应用程序在OS注册.像Whatsapp和facebook一些其他著名的应用程序。

    我尝试过服务、警报管理器和调度程序,但没有成功。

    它们提供了一些手动运行服务的特定方式。我检查了Leeco,它使用的是AndroidOS。

    解决MIUI7.0=

    MIUI4.0设置

    MIUI自动启动详细说明

    根据我的说法,您可以尝试使用服务,然后检查它是否有效。

    谢谢,希望你能从中得到一点帮助。

    匿名用户

    是的,它在几乎所有标准/流行的设备中都可以正常工作,例如三星、LG(Nexus 5X)、索尼、摩托罗拉、Pixel…

    我的解决方案:

    每种类型的组件元素的清单条目-

    您需要在AndroidManifest. xml中添加此字符串android:process=":service"

    像这样:

    ... 
    
    <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" />
    
    ...
    

    我已经在小米5s上测试了这个解决方案。工作了!!!

    IMHO似乎每当用户退出应用程序时,小米固件都会杀死主进程…

    匿名用户

    可能这些中国手机已经禁用了接收警报事件的应用程序唤醒以节省电池寿命。我知道一些中国制造商如果提前关闭应用程序以节省电池电量,则不会唤醒应用程序以接收推送通知。因此,在再次手动打开应用程序之前,它不会被OS唤醒以进行任何事件处理。

    但是,此行为可以更改。检查电源管理设置并进行相应更改,以允许定期或在需要时唤醒应用程序。我认为它可能是受限模式或类似的东西。