Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 關機鬧鐘

android 關機鬧鐘

編輯:關於Android編程

新項目的手機需要實現關機狀態下的鬧鐘,早在剛開始接觸 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 的權限管理機制引起的。  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved