我认为这个问题在 stackoverflow 中被问过很多次,但仍然有很多人在努力解决它。
在我的 android 应用程序中,我必须每半小时唤醒一次设备以获取当前位置并将其发送到服务器。为此,我将 AlarmManager 与 setExactAndAllowWhileIdle() 方法和 WakefulBroadcastReceiver 一起使用。它在三星、LG(Nexus)、索尼、松下、联想、摩托罗拉、Micro max 等几乎所有标准/流行设备上都能正常工作....但其他一些设备大多是中国设备不支持或不允许设备唤醒使用 setExactAndAllowWhileIdle() 从打盹模式。我已经在 leeco letV (Android OS 6.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 设备手动更改了一些设置,例如设置 > 电池 > 对齐唤醒 > 禁用了这两个选项。如果它启用电池可以忽略应用程序的强制唤醒。
我的问题:
在这种设备中发生了什么?为什么他们不允许在特定时间间隔内触发警报?
在某些设备中,例如 Gionee 的 plus 闹钟会延迟 2-3 分钟...为什么?
android.net.conn.CONNECTIVITY_CHANGE 广播接收器在网络连接发生变化时进行监听.....当它在某些设备(如 Gionee s plus)中不工作时该怎么办?
不同制造商的电池优化设置有很多变化......如果解决这个问题,会不会损害我们应用的后台服务。
最佳答案
您好,我在小米 phone.leeco 中测试时遇到了同样的问题,我不太清楚。 小米手机有自己的操作系统,即 MIUI。当我们清除 RAM 时,它会清除所有应用程序,但某些应用程序在操作系统中注册。像 Whatsapp 和 facebook 等一些其他著名的应用程序。
我尝试过 Service、Alarm Manager 和 Scheduler,但都没有成功。
他们提供了一些手动特定的方式来运行服务。我已经检查过 Leeco 它使用的是 Android 操作系统。
MIUI 7.0 解决方案 => 安全 => 自动启动 => 选择要在后台运行的应用程序 => 重启 重启后,您的设备应该能够像其他安卓设备一样在后台运行您的应用程序服务。
MIUI AutoStart Detailed Description
根据我的说法,您可以尝试使用服务,然后检查它是否有效。
谢谢,希望你能从中得到一些帮助。
关于Android AlarmManager.setExactAndAllowWhileIdle() 和 WakefulBroadcastReceiver 在一些新制造的低价设备中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40931966/
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation
我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params
这段代码似乎创建了一个范围从a到z的数组,但我不明白*的作用。有人可以解释一下吗?[*"a".."z"] 最佳答案 它叫做splatoperator.SplattinganLvalueAmaximumofonelvaluemaybesplattedinwhichcaseitisassignedanArrayconsistingoftheremainingrvaluesthatlackcorrespondinglvalues.Iftherightmostlvalueissplattedthenitconsumesallrvaluesw
你能解释一下吗?我想评估来自两个不同来源的值和计算。一个消息来源为我提供了以下信息(以编程方式):'a=2'第二个来源给了我这个表达式来评估:'a+3'这个有效:a=2eval'a+3'这也有效:eval'a=2;a+3'但我真正需要的是这个,但它不起作用:eval'a=2'eval'a+3'我想了解其中的区别,以及如何使最后一个选项起作用。感谢您的帮助。 最佳答案 您可以创建一个Binding,并将相同的绑定(bind)与每个eval相关联调用:1.9.3p194:008>b=binding=>#1.9.3p194:009>eva
我无法运行Spring。这是错误日志。myid-no-MacBook-Pro:myid$spring/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/lib/spring/sid.rb:17:in`fiddle_func':uninitializedconstantSpring::SID::DL(NameError)from/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/li
我的任务是从数组中选择最高和最低的数字。我想我很清楚我想做什么,但只是努力以正确的格式访问信息以满足通过标准。defhigh_and_low(numbers)array=numbers.split("").map!{|x|x.to_i}array.sort!{|a,b|ba}putsarray[0,-1]end数字可能看起来像"80917234100",要通过,我需要输出"9234"。我正在尝试putsarray.first.last,但一直无法弄明白。 最佳答案 有Array#minmax完全满足您需要的方法:array=[80,