日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > android計時與系統休眠

android計時與系統休眠

來源:程序員人生   發布時間:2015-03-17 08:41:26 閱讀次數:3093次

android計時與系統休眠


TIP:可能寫的有點倉促,具體的可以聯系我(*^__^*)

1.摘要:

      之前做項目的時候,修改1個倒計時秒表,本來以為比較簡單,但是發現很多有趣的東西。我們項目里面用的是Timer計時的方法,但是,當系統休眠的時候,Timer也是處于休眠狀態的。后來,我改進了幾個方法,1個是handle+message的方法,還有1個是handle+runnable的方法,還有handle+Thread的方法。但是一樣發現系統休眠的時候,這些一樣是處于休眠狀態的。后來上網查找了1下,這和android的架構有關:


2.原理

        Android手機有兩個處理器,1個叫Application Processor(AP),1個叫Baseband Processor(BP)。AP是ARM架構的處理器,用于運行Linux+Android系統;BP用于運行實時操作系統(RTOS),通訊協議棧運行于BP的RTOS之上。非通話時間,BP的能耗基本上在5mA左右,而AP只要處于非休眠狀態,能耗最少在50mA以上,履行圖形運算時會更高。另外LCD工作時功耗在100mA左右,WIFI也在100mA左右。1般手機待機時,AP、LCD、WIFI均進入休眠狀態,這時候Android中利用程序的代碼也會停止履行。Android為了確保利用程序中關鍵代碼的正確履行,提供了Wake Lock的API,AlarmManager這個類使用的是BP的芯片,使得利用程序有權限通過代碼禁止AP進入休眠狀態。但如果不領會Android設計者的意圖而濫用Wake Lock API,為了本身程序在后臺的正常工作而長時間禁止AP進入休眠狀態,就會成為待電機池殺手。

      首先,完全沒必要擔心AP休眠會致使收不到消息推送。通訊協議棧運行于BP,1旦收到數據包,BP會將AP喚醒,喚醒的時間足夠AP履行代碼完成對收到的數據包的處理進程。其它的如Connectivity事件觸發時AP一樣會被喚醒。那末唯1的問題就是程序如何履行向服務器發送心跳包的邏輯。你明顯不能靠AP來做心跳計時。Android提供的Alarm Manager就是來解決這個問題的。Alarm應當是BP計時(或其它某個帶石英鐘的芯片,不太肯定,但絕對不是AP),觸發時喚醒AP履行程序代碼。那末Wake Lock API有啥用呢?比如心跳包從要求到應對,比如斷線重連重新登陸這些關鍵邏輯的履行進程,就需要Wake Lock來保護。而1旦1個關鍵邏輯履行成功,就應當立即釋放掉Wake Lock了。兩次心跳要求間隔5到10分鐘,基本不會怎樣耗電。除非網絡不穩定,頻繁斷線重連,那種情況辦法不多。

      網上有說使用AlarmManager,由于AlarmManager 是Android 系統封裝的用于管理 RTC 的模塊,RTC (Real Time Clock) 是1個獨立的硬件時鐘,可以在 CPU 休眠時正常運行,在預設的時間到達時,通過中斷喚醒 CPU。

 

3.實驗

      后來,本人使用AlarmManager,但是又碰到不準的問題,而且當系統繁忙的時候(比如剛開機前1分鐘),更加明顯,后來查看官方的API說明。由于我之前使用的方法大致是下面的原理:

[java] view plaincopyprint?
  1. AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);  
  2. Intent intent = new Intent("com.liu.alarm.ACTION_SEND");  
  3. PendingIntent sendIntent = PendingIntent.getBroadcast(this0, intent,PendingIntent.FLAG_UPDATE_CURRENT);  
  4. am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000,1000, sendIntent);
然后注冊1個廣播接收器接收
  1. public void onReceive(final Context context, Intent intent) {  

  2. 需要的操作;}
      我們看看官方給出的API說明:Note: as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whosetargetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.意思大概是說19或19以后,為了優化電池,該計時操作不準確了(可能在定義時間以后響應),但是19之前的任然準確。

If your application has strong ordering requirements there are other APIs that you can use to get the necessary behavior; see setWindow(int, long, long, PendingIntent) andsetExact(int, long, PendingIntent).意思是雖然19(包括)以后可能不準確,但是android保存了兩個接口,這兩個接口是準確的。本人因而使用了這其中1個。

方法以下    TIP:條件是確保你的API是19的或更高,否則做下判斷

public static boolean isKitKatOrLater() {

 return Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2;

}


[java] view plaincopyprint?
  1. AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);  
  2. Intent intent = new Intent("com.liu.alarm.ACTION_SEND");  
  3. PendingIntent sendIntent = PendingIntent.getBroadcast(this0, intent,PendingIntent.FLAG_UPDATE_CURRENT);</span>  
[java] view plaincopyprint?
  1. if(isKitKatOrLater(){
  2. am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);
  3. }else{
  4. am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);

然后注冊1個廣播接收器接收

[java] view plaincopyprint?
  1. public void onReceive(final Context context, Intent intent) {
  2. if(isKitKatOrLater(){
  3. am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent); 
  4. }else{
  5. am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);
  6. }  

[java] view plaincopyprint?
  1. if(isKitKatOrLater(){
  2. am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);   
  3. 需要的操作;}
       但是后來有發現,即便使用了精確的時間計時,但是在系統剛開機的1分鐘內計時,依然會有不及時響應的情況,所以,后來自己想了1下,畢竟是兩塊芯片,多進程多線程還要斟酌好多同步的問題,兩塊芯片也不可能配合的那末完美無缺,假設1塊特別繁忙的時候。所以,后來我參考源碼的方法:正常情況下使用線程或Timer計時,并且使用AlarmManager設定1個計時結束的時間,當履行Activity的Onpause的時候使用AlarmManager的計時響應。當Onresume的時候,根據走過的時間刷新界面。下面是我全部的代碼
/** * 2014⑴2-05 BenMin FEIXUN_DESKCLOCK_BENMIN_001 * modify PWEUN⑷141 to remind the user when the timing is over. * 2014⑴2⑴7 BenMin FEIXUN_DESKCLOCK_BENMIN_002 * modify to ensure the fragment attached to Activity when using getResources() function. * 2014⑴2⑵6 BenMin FEIXUN_DESKCLOCK_BENMIN_003 * modify PLGN⑷89 to stop the ring when press the back menu. */ package com.phicomm.keyer; import java.util.Timer; import java.util.TimerTask; import android.R.integer; import android.app.AlarmManager; import android.app.AlertDialog; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.media.MediaPlayer; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.NumberPicker; import android.widget.NumberPicker.Formatter; import android.widget.NumberPicker.OnValueChangeListener; import android.widget.TextView; import com.phicomm.deskclock.DeskClockFragment; import com.phicomm.deskclock.FxDeskClock; import com.phicomm.deskclock.R; public class FxKeyerFragment extends DeskClockFragment implements OnClickListener, Formatter, OnValueChangeListener { private NumberPicker keyerHour; private NumberPicker keyerMinute; private NumberPicker keyerSecond; private Button kbtnStart; private Button kbtnPause; private Button kbtnReset; private LinearLayout time; private TextView hour; private TextView minute; private TextView second; private int hourtime; private int minutetime; private int secondtime; private Timer timer; private TimerTask task; private MediaPlayer alarmMusic; private AlertDialog dialog = null; private static final int originState = 0; //original state private static final int timerState = 1; //timer state private static final int pauseState = 2; //pause private static final int resetState = 3; //reset private static final int overState = 4; //over private int stateNow = originState; Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 1){ if(secondtime > 0) { secondtime --; second.setText(format(secondtime)); } else if(minutetime > 0) { minutetime --; secondtime = 59; second.setText(format(secondtime)); minute.setText(format(minutetime)); } else if(hourtime > 0) { hourtime --; secondtime = 59; minutetime = 59; second.setText(format(secondtime)); minute.setText(format(minutetime)); hour.setText(format(hourtime)); } if (hourtime <= 0 && minutetime <= 0 && secondtime <= 0) { startRing(); } } } }; private AlarmManager mAlarmManager; private PendingIntent sendIntent; public static String ALARM_KEYER_ACTION = "com.phicomm.keyer.alarm_keyer_action"; private BroadcastReceiver mBroadcastReceiver; private boolean isRing = false; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); mAlarmManager = (AlarmManager) this.getActivity().getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(); intent.setAction(ALARM_KEYER_ACTION); sendIntent = PendingIntent.getBroadcast(getActivity(), 0, intent , PendingIntent.FLAG_UPDATE_CURRENT); mBroadcastReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context arg0, Intent arg1) { // TODO Auto-generated method stub kbtnPause.setEnabled(false); startRing(); } }; IntentFilter filter = new IntentFilter(ALARM_KEYER_ACTION); getActivity().registerReceiver(mBroadcastReceiver, filter ); } private void startRing(){ if (timer != null) { timer.cancel(); } stateNow = overState; if (isAdded() && isRing == false) { kbtnPause.setTextColor(getResources().getColor(R.color.text_summery)); alarmMusic = MediaPlayer.create(getActivity(), R.raw.in_call_alarm); alarmMusic.setLooping(true); alarmMusic.start(); isRing = true; AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setTitle(R.string.tip) .setMessage(R.string.tip_text) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // TODO Auto-generated method stub alarmMusic.stop(); alarmMusic.release(); alarmMusic = null; isRing = false; } }); dialog = builder.setCancelable(false).create(); dialog.show(); } mAlarmManager.cancel(sendIntent); startTime = 0; leftTimeToRun = 0; ringTime = 0; adjustTime = 0; setNumberPicker(0); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View v = inflater.inflate(R.layout.keyer, container, false); keyerHour = (NumberPicker) v.findViewById(R.id.keyer_hour); keyerHour.setMinValue(0); keyerHour.setMaxValue(23); keyerHour.setFormatter(this); keyerHour.setOnValueChangedListener(this); keyerHour.getChildAt(0).setFocusable(false); keyerMinute = (NumberPicker) v.findViewById(R.id.keyer_minute); keyerMinute.setMinValue(0); keyerMinute.setMaxValue(59); keyerMinute.setFormatter(this); keyerMinute.setOnValueChangedListener(this); keyerMinute.getChildAt(0).setFocusable(false); keyerSecond = (NumberPicker) v.findViewById(R.id.keyer_second); keyerSecond.setMinValue(0); keyerSecond.setMaxValue(59); keyerSecond.setFormatter(this); keyerSecond.setOnValueChangedListener(this); keyerSecond.getChildAt(0).setFocusable(false); kbtnStart = (Button) v.findViewById(R.id.kbtnStart); kbtnStart.setOnClickListener(this); kbtnPause = (Button) v.findViewById(R.id.kbtnPause); kbtnPause.setOnClickListener(this); kbtnReset = (Button) v.findViewById(R.id.kbtnReset); kbtnReset.setOnClickListener(this); time = (LinearLayout) v.findViewById(R.id.time); hour = (TextView) v.findViewById(R.id.hour); minute = (TextView) v.findViewById(R.id.minute); second = (TextView) v.findViewById(R.id.second); TimeAllZero(); return v; } @Override public void onResume() { if (getActivity() instanceof FxDeskClock) { ((FxDeskClock) getActivity()).registerPageChangedListener(this); } long now = SystemClock.elapsedRealtime(); if(now <= ringTime && stateNow == timerState){ long leftTime = ringTime - now; setNumberPicker(leftTime); } if(stateNow == overState) { setNumberPicker(0); } super.onResume(); } private void setNumberPicker(long leftTime){ long secs = leftTime/1000; int hours = (int) (secs/3600); int minutes = (int) ((secs%3600)/60); int seconds = (int) ((secs%3600)%60); secondtime = seconds; minutetime = minutes; hourtime = hours; second.setText(format(seconds)); minute.setText(format(minutes)); hour.setText(format(hours)); } @Override public void onPause() { if (getActivity() instanceof FxDeskClock) { ((FxDeskClock) getActivity()).unregisterPageChangedListener(this); } super.onPause(); } public String format(int value) { String tmpStr = String.valueOf(value); if (value < 10) { tmpStr = "0" + tmpStr; } return tmpStr; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.kbtnStart: TimeAllZero(); Start(); break; case R.id.kbtnPause: Pause(); break; case R.id.kbtnReset: Reset(); kbtnStart.setTextColor(getResources().getColor(R.color.text_summery)); break; } } public void onValueChange(NumberPicker picker, int oldVal, int newVal) { if (picker == keyerHour) { hourtime = newVal; } if (picker == keyerMinute) { minutetime = newVal; } if (picker == keyerSecond) { secondtime = newVal; } TimeAllZero(); } private long startTime = 0; private long leftTimeToRun = 0; private long ringTime = 0; private long adjustTime = 0; public void Start() { if (kbtnStart.isEnabled()) { kbtnStart.setVisibility(View.GONE); time.setVisibility(View.VISIBLE); hour.setText(format(hourtime)); minute.setText(format(minutetime)); second.setText(format(secondtime)); kbtnPause.setVisibility(View.VISIBLE); kbtnPause.setText(R.string.kpause); kbtnPause.setEnabled(true); kbtnPause.setTextColor(getResources().getColor(R.color.text_gray)); kbtnReset.setText(R.string.kreset); kbtnReset.setVisibility(View.VISIBLE); keyerHour.setVisibility(View.GONE); keyerMinute.setVisibility(View.GONE); keyerSecond.setVisibility(View.GONE); timer = null; task = null; timer = new Timer(); task = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; timer.schedule(task, 1000, 1000); startTime = SystemClock.elapsedRealtime(); leftTimeToRun = (60 * 60 * hourtime + 60 * minutetime + secondtime) * 1000; ringTime = startTime + leftTimeToRun; mAlarmManager.cancel(sendIntent); if (isKitKatOrLater()) { mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent); } else { mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent); } stateNow = timerState; } } public static boolean isKitKatOrLater() { return Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2; } public void Pause() { if(kbtnPause.getText().toString().equals(getResources().getString(R.string.kpause))) { kbtnPause.setText(R.string.kcontinue); timer.cancel(); adjustTime = (leftTimeToRun - (SystemClock.elapsedRealtime() - startTime)) % 1000; mAlarmManager.cancel(sendIntent); stateNow = pauseState; } else { stateNow = timerState; kbtnPause.setText(R.string.kpause); secondtime = Integer.parseInt(second.getText().toString()); minutetime = Integer.parseInt(minute.getText().toString()); hourtime = Integer.parseInt(hour.getText().toString()); timer = new Timer(); task = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; timer.schedule(task, adjustTime, 1000); startTime = SystemClock.elapsedRealtime(); leftTimeToRun = (60 * 60 * hourtime + 60 * minutetime + secondtime) * 1000 + adjustTime; ringTime = startTime + leftTimeToRun; mAlarmManager.cancel(sendIntent); if (isKitKatOrLater()) { mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent); } else { mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent); } } } public void Reset() { stateNow = resetState; kbtnStart.setVisibility(View.VISIBLE); kbtnPause.setVisibility(View.GONE); kbtnReset.setVisibility(View.GONE); keyerHour.setVisibility(View.VISIBLE); keyerHour.setValue(0); hourtime = 0; keyerMinute.setVisibility(View.VISIBLE); keyerMinute.setValue(0); minutetime = 0; keyerSecond.setVisibility(View.VISIBLE); keyerSecond.setValue(0); secondtime = 0; time.setVisibility(View.GONE); timer.cancel(); startTime = 0; leftTimeToRun = 0; ringTime = 0; adjustTime = 0; mAlarmManager.cancel(sendIntent); } public void TimeAllZero() { if (keyerHour.getValue() == 0 && keyerMinute.getValue() == 0 && keyerSecond.getValue() == 0) { kbtnStart.setEnabled(false); kbtnStart.setTextColor(getResources().getColor(R.color.text_summery)); } else { kbtnStart.setEnabled(true); kbtnStart.setTextColor(getResources().getColor(R.color.text_gray)); } } @Override public void onDestroyView() { // TODO Auto-generated method stub super.onDestroyView(); if (timer != null) { timer.cancel(); timer = null; } if (task != null) { task = null; } if (alarmMusic != null) { alarmMusic.stop(); alarmMusic.release(); alarmMusic = null; if(mBroadcastReceiver!= null){ getActivity().unregisterReceiver(mBroadcastReceiver); } } }



生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产精品综合网 | 毛片毛片毛片 | 国产亚洲综合性久久久影院 | 电影 在线 | 欧美一级大片 | 国产欧美在线观看 | 成人在线中文字幕 | 国产区一区二区三区 | 欧美成人在线免费视频 | 麻豆av在线免费观看 | 国产精品一区免费视频 | 久久久国产一区二区三区 | 激情毛片| 国产精品视频一区二区三区不卡 | 国产精品国产三级国产 | 亚洲成人综合视频 | 免费看成人吃奶视频在线 | 精品国产乱码久久久久久久软件 | 国产精品呻吟久久av凹凸 | 国产高清免费视频 | 色亚洲欧美 | 美女视频网站黄 | 久久久7 | 日产精品久久久一区二区开放时间 | 一区二区三区精品视频 | 男女xx| 久久久天堂国产精品女人 | 中文字幕av一区二区 | av中文天堂| 国产在线导航 | 日本精品黄色 | 2015成人永久免费视频 | 黄色裸体网站 | 久久中国国产 | 性生生活大片免费看视频 | 91视频导航 | 久久香视频 | 91一级| 亚洲аv电影天堂网 | 国产精一区 | 日韩精品久久久久久 |