关于 Android 关机闹钟代码

悟途网 2013年06月10日 09:53 阅读()
字号 (A- A+)

在 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 接口,这些接口实现了图形的描绘以及固定大小的文字显示,函数介绍如下:

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 是在进程去循环读取并处理的,示例代码如下:

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快捷卸载第三方应用

android快捷卸载第三方应用

android快捷卸载第三方应用,1、需要的权限:2、获取所...

如何设置安卓android手机通话接通震动提醒功能

如何设置安卓android手机通话

安卓android手机通话接通震动提醒,进入手机拨号界面,...

分享 Android 五种布局模式

分享 Android 五种布局模式

Android布局是应用界面开发的重要一环,在Android中,共...

分享 Android 内核源代码交叉编译

分享 Android 内核源代码交叉

Android 内核源代码交叉编译,因为我们需要 Android 的模...

Android 6.0中的新技术总结

Android 6.0中的新技术总结

最近 Google 正式发布了 Android M,并命名为“棉花糖”(...

解决Android设备无线连不上及常见无线连接问题

解决Android设备无线连不上及

Android设备越来越多,作为无线终端,常常会遇到各种无...

Android 串行接口(serial port)编程

Android 串行接口(serial port)编

Android 串行接口(serial port)编程,android-serialport-api项目(...

Android安卓手机连接隐藏wifi方法

Android安卓手机连接隐藏wi

安卓手机怎么连接隐藏wifi信号?由于手机运行的安卓版...