代码知识补充
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();//启动服务
}