代码知识补充

本文围绕Android开发进行代码知识补充。介绍了设置窗体始终点亮、修改超时休眠时间的方法,阐述图片存储路径及访问方式。还详细讲解了Android message消息机制,包括Message、MessageQueue、Looper和Handler。此外,对电源管理架构、PowerManagerService及启动过程进行了分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码知识补充

1.设置窗体始终点亮

//设置窗体全屏
getWindow().setFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
		WindowManager.LayoutParams.FLAG_FULLSCREEN);
//设置窗体始终点亮
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
		WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//设置窗体背景模糊
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, 
		WindowManager.LayoutParams.FLAG_BLUR_BEHIND); 

2.修改Android超时休眠时间

方法一、调整代码

Settings.System.putInt(getContentResolver(),
		android.provider.Settings.System.SCREEN_OFF_TIMEOUT,-1);

权限:

<uses-permission android:name="android.permission.WRITE_SETTINGS" />

方法二、直接修改系统数据库自己操作数据库
使用语句:

UPDATE system SET value = 'you_time' WHERE name = 'screen_off_timeout' ; 

3.图片存储路径

App独立文件:这类文件当我们删除应用之后,还应该保留在手机上的,例如拍照的照片,不应该随着删除应用而被删除掉。对于这类文件,Android给我们提供了特定的目录,这些目录都是以DIRECTORY开头的,例如:DIRECTORY_MUSIC , DIRECTORY_PICTURES.
访问这些文件夹有两种方式。
第一种:

File sdCard = Environment.getExternalStorageDirectory();

这个sdCard的路径为mnt/sdcard/ 即为SD卡根路径,我们可以指定访问的文件夹名

File sdCard = Environment.getExternalStorageDirectory();
File directory_pictures = new File(sdCard, "Pictures");
Log.i(TAG,"directory_pictures="+directory_pictures);

第二种:

File directory_pictures = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
Log.e(TAG, "directory_pictures="+directory_pictures);

得到的路径:directory_pictures=mnt/sdcard/Pictures
第二种方法是一个更加方便的访问Android给我们提供好的一些公共目录的方法,第一种方式更加灵活,可以自己指定目录。

Android内部外部文件创建参考:www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0923/1557.html

4.时间日期

 /**          
 	SimpleDateFormat函数语法:                   
 	G 年代标志符    
 	y 年          
 	M 月          
 	d 日          
 	h 时 在上午或下午 (1~12)          
 	H 时 在一天中 (0~23)          
 	m 分          
 	s 秒          
 	S 毫秒          
 	E 星期          
 	D 一年中的第几天          
 	F 一月中第几个星期几          
 	w 一年中第几个星期          
 	W 一月中第几个星期          
 	a 上午 / 下午 标记符          
 	k 时 在一天中 (1~24)          
 	K 时 在上午或下午 (0~11)          
 	z 时区         
 */
 impleDateFormat aDate = new SimpleDateFormat("yyyy-mm-dd  HH:mm:ss");        
 SimpleDateFormat bDate = new SimpleDateFormat("yyyy-mmmmmm-dddddd");        
 long now = System.currentTimeMillis();        
 System.out.println(aDate.format(now));        
 System.out.println(bDate.format(now));                 
 SimpleDateFormat myFmt = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");            
 SimpleDateFormat myFmt1 = new SimpleDateFormat("yy/MM/dd HH:mm");            
 SimpleDateFormat myFmt2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//等价于now.toLocaleString()            
 SimpleDateFormat myFmt3 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E ");            
 SimpleDateFormat myFmt4 = new SimpleDateFormat( "一年中的第 D 天 一年中第w个星期 
 					一月中第W个星期 在一天中k时 z时区");         
 System.out.println(myFmt.format(now));         
 System.out.println(myFmt1.format(now));
 System.out.println(myFmt2.format(now));         
 System.out.println(myFmt3.format(now));         
 System.out.println(myFmt4.format(now));

运行结果:
2017-10-17 11:10:21
2017-000010-000017
2017年10月17日 11时10分21秒
17/10/17 11:10
2017-10-17 11:10:21
2017年10月17日 11时10分21秒 星期二
一年中的第 290 天 一年中第42个星期 一月中第3个星期 在一天中11时 CST时区

private static long parseTime(String strTime) {        
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");        
	long time = 0L;        
	try {            
		time = format.parse(strTime).getTime();        
	} 
	catch (ParseException e) {            
		e.printStackTrace();        
	}        
	return time;    
}    
public static void main(String[] args) {        
	String aString="2017-11-12";        
	long aTime=parseTime(aString);        
	System.out.println(aTime);        
	SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd");        
	System.out.println(aDate.format(aTime));    }

输出结果:
1510416000000
2017-11-12
很方便的实现了string转时间

5.Android message 消息机制介绍及使用

(1)Message
消息对象,顾名思义就是记录消息信息的类。这个类有几个比较重要的字段:
arg1和arg2:我们可以使用两个字段用来存放我们需要传递的整型值,在Service中,我们可以用来存放Service的ID。
obj:该字段是Object类型,我们可以让该字段传递某个多项到消息的接受者中。
what:这个字段可以说是消息的标志,在消息处理中,我们可以根据这个字段的不同的值进行不同的处理,类似于我们在处理Button事件时,通过switch(v.getId())判断是点击了哪个按钮。

在使用Message时,我们可以通过new Message()创建一个Message实例,但是Android更推荐我们通过Message.obtain()或者Handler.obtainMessage()获取Message对象。这并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出并返回这个实例。反之如果消息池中没有可用的Message实例,则根据给定的参数new一个新Message对象。通过分析源码可得知,Android系统默认情况下在消息池中实例化10个Message对象。

//arg1和arg2是成本较低的替代品使用 setData(),如果你只需要存储一些整数值。
//obj是任意对象发送给收件人。
//what是用户定义的消息代码,以便收件人能识别这条消息是关于什么的。

//方法一:使用构造器public Message(); 
Message msg = new Message(); 
msg.arg1 = 1; 
msg.arg2 = 2; 
msg.obj = 3; 
msg.what = 4; 
handle.sendMessage(msg);

//方法二: 使用构造器public static Message obtain()
Message msg = Message.obtain();  
msg.what=1;  
msg.arg1=2;
msg.arg2=3;
msg.obj=4;
handler.sendMessage(msg);   

//方法三: 使用构造器public static Message obtain(Handler handler);  
Message msg = Message.obtain(handler);  
msg.what=1;
msg.arg1=2;
msg.arg2=3;
msg.obj=4;
msg.sendToTarget();

//方法四:使用构造器public static Message obtain(Handler handler, int what);
Message msg = Message.obtain(handler, 1);  
msg.arg1=2;
msg.arg2=3;
msg.obj=4;
msg.sendToTarget();

//方法五:使用构造器public static Message obtain(Handler handler, int what , Object obj);
Message msg = Message.obtain(handler, 1, 4);
msg.arg1=2;msg.arg2=3;msg.sendToTarget();

//方法六:使用构造器public static Message obtain(Handler handler, int what, int arg1 , int arg2);
Message msg = Message.obtain(handler, 1, 2 , 3);
msg.obj=4;
msg.sendToTarget();

//方法七:使用构造器public static Message obtain(Handler handler, int what, int arg1 , int arg2, Object obj);
Message msg = Message.obtain(handler, 1, 2 , 3, 4);
msg.sendToTarget();

//方法八:使用构造器public static Message obtain(Handler handler, int what, int arg1 , int arg2, Object obj);
Message msg = Message.obtain(handler, 1, 2 , 3, 4);
Bundle bundle = new Bundle();
List<integer> list = new ArrayList<integer>();
list.add(5);
list.add(6);
list.add(7);
bundle.putIntegerArrayList("num",ArrayList<integer>list);
msg.setData(bundle);
msg.sendToTarget();

(2)MessageQueue
消息队列,用来存放Message对象的数据结构,按照“先进先出”的原则存放消息。存放并非实际意义的保存,而是将Message对象以链表的方式串联起来的。MessageQueue对象不需要我们自己创建,而是有Looper对象对其进行管理,一个线程最多只可以拥有一个MessageQueue。我们可以通过Looper.myQueue()获取当前线程中的MessageQueue。
(3)Looper
MessageQueue的管理者,在一个线程中,如果存在Looper对象,则必定存在MessageQueue对象,并且只存在一个Looper对象和一个MessageQueue对象。
在Android系统中,除了主线程有默认的Looper对象,其它线程默认是没有Looper对象。如果想让我们新创建的线程拥有Looper对象时,我首先应调用Looper.prepare()方法,然后再调用Looper.loop()方法。典型的用法如下:

class LooperThread extends Thread{    
	public Handler mHandler;    
	public void run()    {        
		Looper.prepare();        
		//其它需要处理的操作        
		Looper.loop();    
	}
}

(4)Handler
消息的处理者。通过Handler对象可以封装Message对象,然后通过sendMessage(msg)把Message对象添加到MessageQueue中;当MessageQueue循环到该Message时,就会调用该Message对象对应的handler对象的handleMessage()方法对其进行处理。由于是在handleMessage()方法中处理消息,因此我们应该编写一个类继承自Handler,然后在handleMessage()处理我们需要的操作。

6.PowerManager分析

一直以来,电源管理是电子产品设计中非常重要的环节,也是任何电子设备中最为重要的系统模块之一,优秀的电源管理方案,能够提供持久的续航能力,良好的用户体验,更能提升电子产品的竞争力。

移动设备的电量主要由两种元件消耗:CPU和显示屏,因此设法降低这两种元件的耗电量就是电源管理的关键,为移动设备设计的CPU大多有两种工作频率,为了省电,大部分时间内cpu都工作在降低频率下,只有进行密集计算时,如视频解码才会切换到高频状态,而显示屏省电的方法是尽量减少亮屏时间,但是显示屏的开关和应用有很大的关系,因此系统中需要有一套机制来控制显示屏的开关和亮度,这也是电源管理的主要工作

电源管理架构

Android的电源管理主要是通过wakelock机制来管理系统的状态,整个android电源管理,可以分为四个层次:应用接口层(PowerManager.java),Framework层(PowerManagerService.java),HAL层(Power.c),和内核层(kernel/Power)
应用接口层:PowerManager中开放给应用一系列接口,应用可以调用PM的接口申请wakelock,唤醒系统,使系统进入睡眠等操作;
Framework层:应用调用PowerManager开放的接口,来对系统进行一些列的操作是在PowerManagerService中完成的,PowerManagerService计算系统中和Power相关的计算,是整个电源管理的决策系统。同时协调Power如何与系统其它模块的交互,比如亮屏,暗屏,系统睡眠,唤醒等等。
HAL层:该层只有一个power.c文件,该文件通过上层传下来的参数,向/sys/power/wake_lock或者/sys/power/wake_unlock文件节点写数据来与kernel进行通信,主要功能是申请/释放锁,维持屏幕亮灭 Kernel层:
内核层 实现电源管理的方案主要包含三个部分:
1、Kernel/power/:实现了系统电源管理框架机制。
2、Arch/arm(ormips or powerpc)/mach-XXX/pm.c:实现对特定板的处理器电源管理。
3、drivers/power:是设备电源管理的基础框架,为驱动提供了电源管理接口。

Android电源管理框架如下图:
在这里插入图片描述

电源管理服务——PowerManagerService

PowerManagerServcie是android系统电源管理的核心服务,它在Framework层建立起一个策略控制方案,向下决策HAL层以及kernel层来控制设备待机状态,控制显示屏,背光灯,距离传感器,光线传感器等硬件设备的状态。向上提供给应用程序相应的操作接口,比如听音乐时持续保持系统唤醒,应用通知来临唤醒手机屏幕等场景。

启动过程

SystemServer在系统启动的时候会启动三类服务:引导关键服务,核心服务,其他服务;PowerManagerService是在SystemServer中创建的,并将其作为一个系统服务加入到ServiceManager中:

mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

在启动引导关键服务调用startBootstrapServices(),其中各种服务都是通过SystemServiceManager中的startService()函数来启动:

public <T extends SystemService> T startService(Class<T> serviceClass) {
	final String name = serviceClass.getName(); 
	final T service;            
	Constructor<T> constructor = serviceClass.getConstructor(Context.class);            
	service = constructor.newInstance(mContext);
	mServices.add(service);//注册服务到服务列表中去  
	service.onStart();//启动服务
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值