android 關機鬧鐘

來源:互聯網
上載者:User

新項目的手機需要實現關機狀態下的鬧鐘,早在剛開始接觸 android 的時候都在想為什麼 android 不支援關機狀態下的一些功能呢?像充電或者鬧鐘什麼的,雖然每個平台的驅動不一樣但上層應用是可以提供統一介面的呀,果然在 4.0 的時候支援關機充電了,關機鬧鐘仍然不在預設支援中。市場上的很多品牌手機也都不支援這個功能,讓很多用慣了 Feature Phone 以及擔心輻射的使用者都不習慣。這次做關機鬧鐘在一些思路上借鑒了關機充電的實現方法。整體思路如下:在 uboot 中通過 PMU 判斷開機的原因,如果是 RTC 模組使能開機則在 uboot 中傳遞啟動參數 androidboot.mode=alarm,然後在 init 進程中判斷啟動模式(當前系統有 3 種啟動模式:normal、charger、alarm),如果是 alarm 模式則啟動 alarm 服務,alarm 服務與應用程式 alarm關聯,因此需要編寫應用程式來實現關機鬧鐘的功能。應用程式主要實現以下幾個個方面的功能:1、顯示關機鬧鐘的 UI 以及目前時間;2、播放鬧鈴;3、讀取 input 事件判斷使用者操作;4、使用者可以在 UI 中選擇懶人模式、開機或者關機。下面逐個解析這幾個功能的實現:1、UI在 zygote 沒有啟動之前完成 UI 顯示可以參考 charger 的做法,用 android 的 minui 介面,這些介面實現了圖形的描繪以及固定大小的文字顯示,函數介紹如下:[cpp] int gr_init(void);             /* 初始化圖形顯示,主要是開啟裝置、分配記憶體、初始化一些參數 */  void gr_exit(void);            /* 登出圖形顯示,關閉裝置並釋放記憶體 */    int gr_fb_width(void);         /* 擷取螢幕的寬度 */  int gr_fb_height(void);        /* 擷取螢幕的高度 */  gr_pixel *gr_fb_data(void);    /* 擷取顯示資料緩衝的地址 */  void gr_flip(void);            /* 重新整理顯示內容 */  void gr_fb_blank(bool blank);  /* 清屏 */    void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);  /* 設定字型顏色 */  void gr_fill(int x, int y, int w, int h);  /* 填充矩形地區,參數分別代表起始座標、矩形地區大小 */  int gr_text(int x, int y, const char *s);  /* 顯示字串 */  int gr_measure(const char *s);             /* 擷取字串在預設字型檔中佔用的像素長度 */  void gr_font_size(int *x, int *y);         /* 擷取當前字型檔一個字元所佔的長寬 */    void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy);  /* 填充由source指定的圖片 */  unsigned int gr_get_width(gr_surface surface);   /* 擷取圖片寬度 */  unsigned int gr_get_height(gr_surface surface);  /* 擷取圖片高度 */  /* 根據圖片建立顯示資源資料,name為圖片在mk檔案指定的相對路徑 */  int res_create_surface(const char* name, gr_surface* pSurface);  void res_free_surface(gr_surface surface);       /* 釋放資源資料 */  圖片只支援 png 格式,做這個 UI 的圖片資源花了不少時間(沒做過美工),一般圖片的顯示先由 res_create_surface 建立資源資料,然後調用 gr_blit 填充,最後調用 gr_flip 重新整理顯示。在關機鬧鐘的介面還需要顯示目前時間,最開始調用 minui 預設的字型檔來顯示,但是預設字型檔的字型太小了,只支援 10 x 18 ASIC-II 編碼的字元,效果很不好,後來就把時間需要的 10 個數字以及符號以圖片的形式顯示。2、鬧鈴在這個階段播放鬧鈴只能選擇 tinyplay,tinyplay 是 android 內建的一款簡易播放器,只能播放固定格式的 wav 檔案。UI 顯示以及播放鬧鈴分別獨佔一個線程,以保證各自不被幹擾。3、input evnt當鬧鐘開始響後,使用者可以通過觸控螢幕點擊選擇是否開關機或者進入懶人模式,這裡就需要對使用者操作做出判斷,即在程式中去讀取 /dev/input 下面裝置的資料。當進入懶人模式後會停止鬧鈴 5 分鐘再響,這個階段需要關閉 lcd 和 觸控螢幕,使用者可以通過按鍵喚醒 lcd。input event 是在進程去迴圈讀取並處理的,範例程式碼如下:[cpp]  static int event_loop(void)  {      int i;      int ret = 0;      int nfds = ALARM_MAX_DEVICE;      struct input_event event;      const char *device = NULL;      const char *device_path = "/dev/input";        ret = scan_dir(device_path);   /* 掃描該目錄下的裝置節點,我們只開啟觸控螢幕和按鍵 */      if(ret < 0) {          printf("scan dir failed for %s.\n", device_path);          return ret;      }        for(;;) {          poll(ufds, nfds, -1);      /* 輪詢檢測是否有觸控螢幕或者按鍵事件 */            for (i = 0; i < nfds; i++) {              if(ufds[i].revents) {  /* have valid value. */                  if(ufds[i].revents & POLLIN) {                      ret = read(ufds[i].fd, &event, sizeof(event));      /* 讀取事件 */                      if (ret < (int)sizeof(event)) {                          printf("could not get event.\n");                          continue;                      }                      handle_event(event.type, event.code, event.value);  /* 處理事件 */                  }              }          }      }        return 0;  }  附:android 許可權管理機制這次在編譯使用 alarm 的時候遇到了一個關於許可權的問題:編譯出來的 alarm 可執行程式在 out 目錄下面是擁有可執行許可權的,但是在燒錄到機器後發現沒有可執行許可權了,最後才發現是 android 的許可權管理機制引起的。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.