首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >安卓AlarmManager.setExactAndAllowWhileIdle()和WakefulBroadcastReceiver在一些新制造的低价设备上不起作用

安卓AlarmManager.setExactAndAllowWhileIdle()和WakefulBroadcastReceiver在一些新制造的低价设备上不起作用
EN

Stack Overflow用户
提问于 2016-12-02 20:12:42
回答 4查看 7.4K关注 0票数 27

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

在我的android应用程序中,我必须每半小时唤醒一次设备,以获取当前位置并将其发送到服务器。它工作正常,几乎所有的标准/流行的设备,如三星,LG(Nexus),索尼,松下,联想,摩托罗拉,Micro max等on....But一些其他设备主要是中国的设备不支持或不能让设备从睡眠模式唤醒与setExactAndAllowWhileIdle()

下面我已经提到了我的代码部分:

代码语言:javascript
复制
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);
    }
}

代码语言:javascript
复制
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设备手动更改了一些设置,如设置>电池>对齐唤醒>禁用这两个选项。

我的问题:

  1. 在这样的设备里发生了什么?为什么?
  2. android.net.conn.CONNECTIVITY_CHANGE广播接收器在网络连接改变时侦听.....What当它在一些设备上不起作用时怎么办?
  3. 对于各种manufacturer....Is的电池优化设置有很多变化它可能会损害我们的应用程序的后台服务,如果是,那么这是什么解决方案。
EN

回答 4

Stack Overflow用户

发布于 2016-12-12 21:53:28

嗨,我有同样的问题,同时在小米phone.leeco测试,我没有太多的想法。小米手机有自己的操作系统,也就是MIUI.When,我们清除了内存,清除了操作系统中除部分应用外的所有应用。像Whatsapp和facebook这样一些著名的应用。

我尝试了Service、Alarm Manager和Scheduler,但没有成功。

他们提供了一些手动特定的方式来运行服务。我已经检查了乐视,它使用的是Android操作系统。

Solution for MIUI 7.0 => Security => Autostart =>选择您要在后台运行的应用程序=>重启重启后,您的设备应该能够像其他安卓设备一样在后台运行应用程序服务。

MIUI 4.0 settings

MIUI AutoStart Detailed Description

根据我的说法,你可以尝试使用服务,然后检查它是否工作。

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

票数 3
EN

Stack Overflow用户

发布于 2017-09-05 03:28:29

在我的android应用程序中,我必须每隔15分钟唤醒设备以获取当前位置并将其发送到服务器。

我已经在小米5s (安卓6.0.1)上测试过了。当我关闭应用程序时,应用程序进入休眠状态:( AlarmManager with setExactAndAllowWhileIdle() not working ¯\_(ツ)_/¯

是的,它在几乎所有的标准/流行设备上都工作得很好,比如三星,LG (Nexus 5X),索尼,摩托罗拉,Pixel…

MY SOLUTION

每种类型的组件元素( <activity><service><receiver><provider> )的清单条目都支持一个android:process属性,该属性可以指定组件应该在其中运行的进程。

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

如下所示:

代码语言:javascript
复制
... 

<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上测试了这个解决方案。是工作!

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

票数 3
EN

Stack Overflow用户

发布于 2016-12-13 02:53:55

可能这些中国手机已经关闭了接收警报事件的应用唤醒功能,以节省电池寿命。我知道一些中国制造商不会唤醒app来接收推送通知,如果他们更早地关闭以节省电池。因此,在再次手动打开应用程序之前,它不会被操作系统唤醒以进行任何事件处理。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40931966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档