通过aAlarmmanger、Service、BroadcastReceiver实现定时访问任务
2017-03-15 13:52
489 查看
定时访问,后台在同样可以执行,但是不能保证进程结束后,依旧可以使用(其实是流氓行为,不应该存在),下面就介绍些有关东西
首先是AlarmManager这个类,获取实例不用说没重点说下其中的一些方法:setRepeating(),这个方法可以按照设定一个延迟时间,然后再设定一个重复循环的时间即可实现循环(定时启动)的任务,但是有一个很重要的东西,源码中有写:
第一个传入参数是精准类型,第二个是延时时间,第三个是启动频率(定时启动),第四个是启动操作的intent,这些都很正常,但你会发现,几乎所有的AlarmManager中的方法都有调用setImpl()这个方法,不难看出,这个方法中的legacyExactLength(),比较重要,决定了是否可以精确传递(多看源码有好处),再看看这个方法:
需要获取mAlwaysExact的判断结果,其中的WINDOW_EXACT表示的精确传递,WINDOW_HEURISTIC表示因为系统休眠或者需要省电的事项来降低精确度,现在看看mAlwaysExact的获取:
可以直接看出,mAlwaysExact的获取是根据版本号的判断,KITKAT指的就是系统APi=19,也就是5.0的情况,大于5.0的时候返回值就是false,也就是不能精确传递了(也就是为和说19之后不会再精准传递的原因)那什么可以可以使用啊,有setWindow(~),和setExact(~)方法是可以精确传递的,这样就可以使用了,但是!!!!!当Api>23(6.0)的时候。。。又抓狂了https://developer.android.google.cn/training/monitoring-device-state/doze-standby.html
这个网址可以查看下确切的内容,只能使用 setAndAllowWhileIdle()或者 setExactAndAllowWhileIdle(),好吧,这样就有三个情况了,分析完了,来讲下思路:
首先进入你需要的界面初始化一个闹钟,这个闹钟就会有三种类型:Api<19,19<Api<23,Api>23三种情况分别对应的方法就是setRepeating(~)、setExact(~)、setExactAndAllowWhileIdle(~),然后你会发现=,=:啊怎么回事只有Api<19的时候才会有,所以这个时候需要定义一个广播接收器,用来接收闹铃广播,然后去启动service,对没错0.0再在service中写个闹钟,然后在发送给广播,广播在启动service然后就可以实现循环了0.0,开干:
首先创建Activity用于写主程序:
启动闹钟,准备receiver的接收:当然先要注册
完成剩下就是service的部分了,还是要在静态注册写好:
以上完结,就这样
然后你想要实现什么请求,直接在线程里写就好了,当然,其实闹钟代码可以自己写个utils类,这就不繁琐啦。祝大家愉快(づ ̄ 3 ̄)づ
首先是AlarmManager这个类,获取实例不用说没重点说下其中的一些方法:setRepeating(),这个方法可以按照设定一个延迟时间,然后再设定一个重复循环的时间即可实现循环(定时启动)的任务,但是有一个很重要的东西,源码中有写:
public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null, null, null, null, null); }
第一个传入参数是精准类型,第二个是延时时间,第三个是启动频率(定时启动),第四个是启动操作的intent,这些都很正常,但你会发现,几乎所有的AlarmManager中的方法都有调用setImpl()这个方法,不难看出,这个方法中的legacyExactLength(),比较重要,决定了是否可以精确传递(多看源码有好处),再看看这个方法:
private long legacyExactLength() { return (mAlwaysExact ? WINDOW_EXACT : WINDOW_HEURISTIC); }
需要获取mAlwaysExact的判断结果,其中的WINDOW_EXACT表示的精确传递,WINDOW_HEURISTIC表示因为系统休眠或者需要省电的事项来降低精确度,现在看看mAlwaysExact的获取:
/** * package private on purpose */ AlarmManager(IAlarmManager service, Context ctx) { mService = service; mPackageName = ctx.getPackageName(); mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion; mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT); mMainThreadHandler = new Handler(ctx.getMainLooper()); }
可以直接看出,mAlwaysExact的获取是根据版本号的判断,KITKAT指的就是系统APi=19,也就是5.0的情况,大于5.0的时候返回值就是false,也就是不能精确传递了(也就是为和说19之后不会再精准传递的原因)那什么可以可以使用啊,有setWindow(~),和setExact(~)方法是可以精确传递的,这样就可以使用了,但是!!!!!当Api>23(6.0)的时候。。。又抓狂了https://developer.android.google.cn/training/monitoring-device-state/doze-standby.html
这个网址可以查看下确切的内容,只能使用 setAndAllowWhileIdle()或者 setExactAndAllowWhileIdle(),好吧,这样就有三个情况了,分析完了,来讲下思路:
首先进入你需要的界面初始化一个闹钟,这个闹钟就会有三种类型:Api<19,19<Api<23,Api>23三种情况分别对应的方法就是setRepeating(~)、setExact(~)、setExactAndAllowWhileIdle(~),然后你会发现=,=:啊怎么回事只有Api<19的时候才会有,所以这个时候需要定义一个广播接收器,用来接收闹铃广播,然后去启动service,对没错0.0再在service中写个闹钟,然后在发送给广播,广播在启动service然后就可以实现循环了0.0,开干:
首先创建Activity用于写主程序:
package test.ban.com.test_alarm; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.util.Log; public class MainActivity extends AppCompatActivity { private AlarmManager alarmManager; private long TIME_INTERVAL = 3000L; private PendingIntent pendingIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); Intent i = new Intent(this, AlarmReceiver.class); pendingIntent = PendingIntent.getBroadcast(this, 0, i, 0); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Log.i(TAG, "M"); alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent); }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Log.i(TAG, "KITKAT"); alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent); } else { Log.i(TAG, "other "); alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), TIME_INTERVAL, pendingIntent); } } private static final String TAG = "MainActivity"; }
启动闹钟,准备receiver的接收:当然先要注册
<receiver android:name=".AlarmReceiver"></receiver>
package test.ban.com.test_alarm; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; /** * Created by brander on 2017/3/15. */ public class AlarmReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Intent i = new Intent(context, MyService.class); context.startService(i); } }
完成剩下就是service的部分了,还是要在静态注册写好:
<service android:name=".MyService"></service>
package test.ban.com.test_alarm; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.Build; import android.os.IBinder; import android.os.SystemClock; import android.support.annotation.Nullable; import android.util.Log; import java.util.Date; /** * Created by brander on 2017/3/15. */ public class MyService extends Service { private long TIME_INTERVAL=3000L; @Nullable @Override public IBinder onBind(Intent intent) { return null; } private static final String TAG = "MyService"; @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "time: " + new Date(). toString()); } }).start(); AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); Intent i = new Intent(this, AlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, i, 0); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Log.i(TAG, "M"); alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+TIME_INTERVAL, pendingIntent); }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Log.i(TAG, "KITKAT"); alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+TIME_INTERVAL, pendingIntent); }else{ Log.i(TAG, "other "); alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), TIME_INTERVAL, pendingIntent); } return super.onStartCommand(intent, flags, startId); } }
以上完结,就这样
然后你想要实现什么请求,直接在线程里写就好了,当然,其实闹钟代码可以自己写个utils类,这就不繁琐啦。祝大家愉快(づ ̄ 3 ̄)づ
相关文章推荐
- 通过crond定时任务自动更新动态IP到PubYun(3322)实现远程访问
- 通过路由器实现用户定时访问网络
- 通过Spring实现定时任务
- Spring 通过配置向 Quartz定时任务 注入service
- 使用ASP.NET实现Windows Service定时执行任务
- 利用ScheduledExecutorService实现定时任务
- 通过ExecutorService实现单例的同步访问控制
- 使用ASP.NET实现Windows Service定时执行任务
- 定时任务实现Timer, TimeTask, ScheduledExecutorService及Spring定时器
- android Service重启问题,结合AlarmManager实现定时任务
- Spring定时任务的实现方式--ScheduledExecutorService
- 通过SSIS实现Oracle与Sqlserver数据库间的数据同步,并定时执行同步任务
- 通过扩展 PriorityBlockingQueue 的 take() 实现任务定时触发
- Java中定时任务的实现:Timer与ScheduledExecutorService的不同
- 通过sql server的作业调度+存储过程来实现系统定时任务的方法
- 使用ASP.NET实现Windows Service定时执行任务
- 通过路由器实现用户定时访问网络
- 通过路由器实现用户定时访问网络
- 通过Shell+atd定时任务,实现jenkins指定时间自动发布任务
- CentOs 7.0实现定时任务(定时访问网页)